[[Prototype]]

属性设置与屏蔽

  1. myObject.foo = "bar";

如果 foo 不直接存在于 myObject 中,而是存在于原型链上层时执行这条赋值命令。

  1. 如果在 [[Prototype]] 上层存在名为 foo普通数据访问属性,则直接在 myObject 中添加新的 foo 属性,是屏蔽属性。
  2. 如果在 [[Prototype]] 上层存在名为 foo只读 (writable:false) 属性, 则这条赋值语句会被忽略,在严格模式下报错。
  3. 如果在 [[Prototype]] 上层存在名为 fooSetter,那么就一定会调用这个 Setter。不会在 myObject 中添加新的 foo 属性。

使用 Object.defineProperty(..) 在任何情况下都可以在 myObject 中添加 foo 属性。

小心隐式屏蔽

  1. var anotherObject = { a: 2 };
  2. var myObject = Object.create(anotherObject);
  3. anotherObject.a; //2
  4. myObject.a; //2
  5. anotherObject.hasOwnProperty("a"); //true
  6. myObject.hasOwnProperty("a"); //false
  7. myObject.a++; //隐式屏蔽 => myObject.a = myObject.a + 1;
  8. anotherObject.a; //2
  9. myObject.a; //3
  10. myObject.hasOwnProperty("a"); //true

“构造函数”

  1. function Foo() {
  2. //...
  3. }
  4. var a = new Foo();

使用 new 来调用函数,会自动执行下面的操作:

  1. 创建一个全新的对象
  2. 将新的对象 [[Prototype]] 关联到函数的 .prototype
  3. 将新的对象绑定到函数调用的 this
  4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。
  1. function Foo() {
  2. //...
  3. }
  4. Foo.prototype = {
  5. /* ... */
  6. };
  7. var a = new Foo();
  8. a.constructor === Foo; //false
  9. a.constructor === Object; //true

a.constructor 委托给了 Foo.prototype,而 Foo.prototype.constructor 属性只是在 Foo 函数声明时的默认属性。

在将 Foo.prototype 指向空对象后,空对象中也没有 .constructor 属性, a.constructor 则委托给了委托链顶端的 Object.prototype,指向了 Object

(原型)继承

  1. function Foo(name) {
  2. this.name = name;
  3. }
  4. Foo.prototype.myName = function () {
  5. return this.name;
  6. };
  7. function Bar(name, label) {
  8. Foo.call(this, name);
  9. this.label = label;
  10. }
  11. //创建了一个新的 Bar.prototype 对象并关联到 Foo.prototype
  12. // Bar.prototype 现在没有 .constructor
  13. Bar.prototype = Object.create(Foo.prototype);
  14. Bar.prototype.myLabel = function () {
  15. return this.label;
  16. };
  17. var a = new Bar("a", "obj a");
  18. a.myName(); // "a"
  19. a.myLabel(); // "obj a"

以下方法使错误的

  1. // 和你想要的机制不一样 直接让 Bar.prototype 直接引用 Foo.prototype ,对其修改会直接修改 Foo.prototype
  2. Bar.prototype = Foo.prototype;
  3. // 基本上满足你的需求 但是可能会有一些副作用
  4. Bar.prototype = new Foo();

ES6 新特性

  1. //ES6之前需要抛弃默认的 Bar.prototype
  2. Bar.prototype = Object.create(Foo.prototype);
  3. //ES6开始直接修改现有的 Bar.prototype
  4. Object.setPrototypeOf(Bar.prototype, Foo.prototype);

检查“类”关系

待补充!!

Object.create(..) polyfill

  1. if (!Object.create) {
  2. Object.create = function (o) {
  3. function F() {}
  4. F.prototype = o;
  5. return new F();
  6. };
  7. }