JavaScript原型——构造函数

没有构造函数,只有对函数的构造调用

构造函数是在类中的知识,很多人以为JavaScript中也有构造函数是因为这样的代码:

function Foo() {
    //...
}

var a = new Foo();

认为Foo是一个类的原因是

  • 看到了关键字new,在面向类中的语言中(比如Java)实例化对象的时候也会用到。
  • Foo()的调用方式类似初始化类的时候类的构造函数的调用方式。

其实,Foo和其它函数没有任何区别。函数本身不是构造函数。当你在普通的函数调用前面加上new关键字之后,就会把这个函数调用变成一个“构造函数调用”。new会劫持所有普通函数并用构造对象的形式来调用它。

举个例子:

function NothingSpecial() {
    console.log("nothing");
}

var a = new NothingSpecial();
//nothing

a;  //NothingSpecial {}

NothingSpecial只是一个普通的函数,但是,使用new调用时,它就会构造一个对象并赋值给a。
函数不是构造函数,当且仅当使用new时,函数调用会变成“构造函数调用”。


有人可能会有疑问,他们也许是因为这样的代码才认为Foo是构造函数的:

function Foo() {
    //...
}

Foo.prototype.constructor === Foo;  //true

var a = new Foo();
a.constructor ===Foo;   //true

Foo.prototype默认有一个公有并且不可枚举的属性.constructor,这个属性引用的是对象关联的函数Foo)。

看起来a.constructor === Foo 意味着a有一个指向Foo的.constructor属性。将.constructor属性指向Foo看作是a对象由Foo“构造“很好理解。但是,事实是这样吗?

function Foo() {
    //...
}

var a = new Foo();
Object.getOwnPropertyNames(a);  //[](并没有constructor属性)

Foo.prototype的.constructor属性只是Foo函数在声明时的默认属性。如果你创建了一个新对象并替换了函数默认的.prototype对象引用,那么新对象并不会自动获得.constructor属性

function Foo() {
    //...
}

//创建一个新原型对象
Foo.prototype = {
    //...
}

var a = new Foo();
a.constructor === Foo;  //false
a.constructor === Object;   //true

很多人认为是Foo()执行了构造工作,但是,如果”constructor”表示”由…构造”,a.constructor应该是Foo,但是并不是这样。
为什么会这样的?我们解释一下:

a没有.constructor属性,它会委托原型链上的Foo.prototype。但是Foo.prototype对象也没有.constructor属性(默认的有),继续委托。委托给顶端的Object.prototype。这个对象有.constructor属性,指向内置的Object()函数。

当然,可以自己手动给Foo.prototype添加一个不可枚举的.constructor属性:

function Foo() {
    //...
}

Foo.prototype = {
    //...
}

Object.defineProperty(Foo.prototype, "constructor", {
    value: Foo,    //让constructor指向Foo
    configurable: false,
    writable: true,
    enumerable: false
});

综上所述,.constructor是一个非常不可靠、不安全的引用,尽量避免使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值