sync github
原型属性 prototype
在函数被定义时创建,初始值是一个"空"对象(没有自身属性的对象)。
为新建对象添加方法和属性的方式
利用原型
// 1 构造器中
function Gadget(name, color) {
this.name = name;
}
// 2 原型属性
Gadget.prototype.price = 66;
几个相关方法和属性
hasOwnProperty()
判断一个属性是自身属性还是原型属性。
通常,在
for in
和for of
中,需要使用hasOwnProperty()
~
propertyIsEnumerable()
该方法会对所有的非内建对象属性返回 true
const newtoy = new Gadget('webcam');
// 对于内建属性和方法来说,不可枚举
newtoy.propertyIsEnumerable('constructor'); // false
// 任何来自原型链中的属性都会返回false,包括那些在`for-in`循环中可枚举的属性
newtoy.propertyIsEnumerable('price'); // false
// notice
newtoy.constructor.prototype.propertyIsEnumerable('price'); // true
isPrototypeOf()
判断当前对象是否是另一个对象的原型Object.getPrototypeOf()
ES5适用。获取对象的原型。效果同 特殊属性__proto__
__proto__
notice: 不要在实际的脚本中使用。另,
__proto__
与prototype
的区别,__proto__
实际上是某个实例对象的属性,而prototype
则属于构造器函数的属性。
原型陷阱
当我们对原型对象执行完全替换时,可能会触发原型链中某种异常
prototype.constructor
属性是不可靠的
体会下面的输出内容
function Dog() {
this.tail = true;
}
var benji = new Dog();
var rusty = new Dog();
Dog.prototype.say = function() {
return 'Woof!';
};
benji.say(); // 'Woof!'
rusty.say(); // 'Woof!'
benji.constructor === Dog; // true
rusty.constructor === Dog; // true
// 用一个自定义的新对象完全覆盖掉原有的原型对象
Dog.prototype = {
paws: 4,
hair: true,
};
// 发现通过构造函数创建的对象 prototype 对象并没有改变
typeof benji.paws; // undefined
benji.say(); // Woof
typeof benji.__proto__.say; // function
typeof benji.__proto__.paws; // undefined
// 通过构造函数创建的对象使用新的 prototype 对象
var lucy = new Dog();
lucy.say(); // TypeError: lucy.say is not a function
lucy.paws; // 4
typeof lucy.__proto__.say; // undefined
typeof lucy.__proto__.paws; // number
//但是!!!注意此时新对象的 constructor 属性的指向
lucy.constructor; // function Object(){[native code]}
benji.constructor; // function Dog() {...}
// solve
Dog.prototype.constructor = Dog;
new Dog().constructor === Dog; // true
lucy.constructor; // function Dog() {...}
当我们重写某对象的
prototype
时, 需要重置相应的constructor
属性。
Summary
来自知乎的一张图,很清晰
Reference
《JavaScript面向对象编程指南》
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。