Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
从来如此,便对么? —鲁迅
对比下MDN中英文下 new操作符
中文:
new 关键字的描述
英文:
new operator Description
developer.mozilla.org/en-US/docs/…
有什么区别呢?
可以看到,中文的翻译将function's prototype object
直接翻译为
原型对象。
那这个prototype
就是“原型”么?
其实不是,这里的 F.prototype
指的是 F
的一个名为 "prototype"
的常规属性。这听起来与“原型”这个术语很类似,但这里我们实际上指的是具有该名字的常规属性。
F.prototype
当我们用new F()
这样的构造函数来创建一个新对象。
如果 F.prototype
是一个对象,那么 new
操作符会使用它为新对象设置 [[Prototype]]
。
举例:
下面是一个例子:
let animal = {
eats: true
};
function Rabbit(name) {
this.name = name;
}
Rabbit.prototype = animal;
let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal
alert( rabbit.eats ); // true
复制代码
设置 Rabbit.prototype = animal
的字面意思是:“当创建了一个 new Rabbit
时,把它的 [[Prototype]]
赋值为 animal
”。
注意:仅在
new F
被调用时才会为新对象的[[Prototype]]
赋值,如果已经创建后又改变F.prototype
,已经创建的对象[[Prototype]]
不会改变。
默认的 F.prototype,构造器属性
每个函数都有"prototype"
属性,不需要我们创建。
默认有一个属性:constructor
对象,指向函数自身
如下:
function Rabbit() {}
/* default prototype
Rabbit.prototype = { constructor: Rabbit };
*/
复制代码
通常,如果我们什么都不做,constructor
属性可以通过 [[Prototype]]
给所有 rabbits 使用:
function Rabbit() {}
// by default:
// Rabbit.prototype = { constructor: Rabbit }
let rabbit = new Rabbit(); // inherits from {constructor: Rabbit}
alert(rabbit.constructor == Rabbit); // true (from prototype)
复制代码
关于 "constructor"
最重要的是
JavaScript 自身并不能确保正确的 "constructor"
函数值。
如果我们换掉了默认的"prototype"
,就不会有 "constructor"
了。
例如:
function Rabbit() {}
Rabbit.prototype = {
jumps: true
};
let rabbit = new Rabbit();
alert(rabbit.constructor === Rabbit); // false
复制代码
所以 为了保险 ,我们在"prototype"
中添加新的属性,不要整体覆盖
function Rabbit() {}
// 不要将 Rabbit.prototype 整个覆盖
// 可以向其中添加内容
Rabbit.prototype.jumps = true
// 默认的 Rabbit.prototype.constructor 被保留了下来
复制代码
或者手动创建constructor
属性。
总结
F.prototype
属性(不要把它与[[Prototype]]
弄混了)在new F
被调用时为新对象的[[Prototype]]
赋值。F.prototype
的值要么是一个对象,要么就是null
:其他值都不起作用。"prototype"
属性仅在设置了一个构造函数(constructor function),并通过new
调用时,才具有这种特殊的影响。
现在再理解一下new的描述:
- 创建一个空的简单JavaScript对象(即
{}
); - 为步骤1新创建的对象添加属性
__proto__
,将该属性链接至构造函数的prototype
属性 ; - 将步骤1新创建的对象作为
this
的上下文 ; - 如果该函数没有返回对象,则返回
this
。