JavaScript-函数2-构造函数

本文介绍了JavaScript中的构造函数和继承机制。通过与Java和TypeScript的对比,详细讲解了JavaScript构造函数的特点及其实例化过程。此外,还探讨了JavaScript基于原型的继承方式,并通过具体示例说明了如何实现继承。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在讲构造函数的时候先看看其他的编程语言是怎么做的:
java

class HelloWorld {
    public HelloWorld() {

    }
}

typescript

class HelloWorld {
    /**
     * 构造函数
     */
    public constructor() {

    }
}

反观JavaScript你会发现它就简单的多了,函数同时兼具类与构造函数两份职责,如下:

function HelloWorld() {

}

在JavaScript的构造函数中,通常我们将函数首字母大写,用以区分构造函数与普通函数。

构造函数的实例化

与很多其他的编程语言类似,JavaScript生成对象也是通过new关键字

function Person(name,age) {
    this.name = name;
    this.age = age;
    this.speak = function() {
        console.log('my name is:'+this.name+',and i am '+this.age+' years old');
    }
}
var xm = new Person('xiaoming',10);
xm.speak();

new关键字的机制
在JavaScript中使用new关键字生成一个对象实例时,经过了以下几个步骤:
new关键字运行机制
1 创建了一个新的空对象,将this指向这个对象
2 设置这个新对象的proto属性,并将proto指向构造函数的原型对象
3 判断返回值,如果无返回值或返回值为this或返回值为非对象,则返回这个对象

function Person(name,age) {
    this.name = name;
    this.age = age;
}
Person.prototype.speak = function() {
    console.log('my name is:'+this.name+',and i am '+this.age+' years old');
}

function SuperMan(name,age) {
    Person.call(this,name,age);
}
var sm = new SuperMan('Clark Kent',20);

如上代码,所示,生成sm对象时一共经历了下面几个阶段:
1: var obj = {};this = obj;
2: this.name = name;this.age = age;
3: return obj;

继承
JavaScript基于原型继承,这里我们可以把原型看成是一个模版,而继承的东西则存在于这个模版当中,所以JavaScript的继承并不是拷贝,而是链接。想象一下有一串珠子o-o-o-o-o。它们被一条原型链连接了起来,位于最右端的珠子可以拿到位于它左面的珠子的属性和方法,但这个顺序是不可逆的(即不能自左向右)。

还是这个例子:

function Person(name,age) {
    this.name = name;
    this.age = age;
}
Person.prototype.speak = function() {
    console.log('my name is:'+this.name+',and i am '+this.age+' years old');
}

function SuperMan(name,age) {
    Person.call(this,name,age);
}
SuperMan.prototype = Object.create(Person.prototype);
SuperMan.prototype.constructor = SuperMan;
var sm = new SuperMan('Clark Kent',20);
sm.speak();

这里我们使用的是一种叫做“寄生组合的方式实现继承”,JavaScript实现继承的方式有很多种。只要理解了原型这个东西,要实现其他几种都是一样的套路。
下面说一下“寄生组合的方式实现继承”的几个重要的点:
- prototype这个属性就叫做原型,原型是一个对象,prototype.constructor指向构造函数
- SuperMan.prototype = Object.create(Person.prototype)这一句将SuperMan的原型指向了一个通过Object.create构造的Person的实例,目的是为了要继承Person中的方法
- SuperMan.prototype.constructor = SuperMan,这一句是将原型中的构造函数修改为SuperMan.未修改之前constructor指向Person
- Person.call(this,name,age),这一句通过call方法继承Person的属性。
这样一来SuperMan便能继承Person的属性和方法。为什么使用这种继承方式,下次可以讲一下JavaScript的几种继承方法与对比,便能了解了。

函数中的this指向
JavaScript的this关键字一直都是个坑,想我当初也是被他伤害的体无完肤啊,谁叫我很久之前还做过java呢,说到java,那么我们就对比一下java中的this与JavaScript中的this吧。
- java中的this
在类中使用,就代表着这个类的实例,一般是不会变的(不知道我这样理解对不对,不对请见谅)
- JavaScript中的this
一句话,函数被谁调用this就指向谁

下面通过几个例子来讲一下:

function Person(name) {
    this.name = name;
    this.speak = function() {
        console.log('Hello,I am '+this.name);
    }
}
var xm = new Person('小明');
xm.speak();//Hello,I am 小明

这种方式应该是this关键字使用的经典场景了,this指向也是没什么疑问的。

var button = document.getElementById('button');
function Person(name) {
    this.name = name;
    this.speak = function() {
        console.log('Hello,I am '+this.name);
    }
}
var xm = new Person('小明');
button.onClick = xm.speak;
button.onClick();//Hello,I am undefined

再看看这个例子,我们有一个按钮,并且为按钮添加一个点击事件,恰巧这个事件函数就是xm.speak。当点击按钮时事件函数就会被调用。但是这里的this.name却为undefined,因为这里的this已经指向button了,而button中并没有name属性。所以始终记住:函数被谁调用this就指向谁.而这里调用这个函数的是button。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值