它做了 5 件事:
- 它创建一个新对象。这个对象的类型很简单object.
- 它设置这个新对象的内部,不可访问,
[[prototype]]
(i.e. __proto__
) 属性是构造函数的外部、可访问的,prototype
对象(每个函数对象自动有一个prototype
财产)。
- 它使得
this
变量指向新创建的对象。
- 它执行构造函数,每当
this
被提到。
- 它返回新创建的对象,除非构造函数返回一个非
null
对象引用。在这种情况下,将返回该对象引用。
Note: 构造函数指的是后面的函数new
关键字,如
new ConstructorFunction(arg1, arg2)
完成此操作后,如果请求新对象的未定义属性,脚本将检查该对象的[[prototype]]
相反,该属性的对象。这就是如何获得类似于 JavaScript 中传统类继承的东西。
最困难的部分是第 2 点。每个对象(包括函数)都有这个内部属性,称为[[prototype]]
。它可以only在对象创建时设置,或者使用new
, with Object.create
,或基于文字(函数默认为Function.prototype
, 数字到Number.prototype
, ETC。)。它只能通过以下方式读取Object.getPrototypeOf(someObject)
。有no其他获取或设置该值的方法。
除了隐藏功能之外[[prototype]]
属性,还有一个属性称为原型,您可以访问和修改它,以便为您创建的对象提供继承的属性和方法。
这是一个例子:
ObjMaker = function() { this.a = 'first'; };
// `ObjMaker` is just a function, there's nothing special about it
// that makes it a constructor.
ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible `prototype` property that
// we can alter. I just added a property called 'b' to it. Like
// all objects, ObjMaker also has an inaccessible `[[prototype]]` property
// that we can't do anything with
obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called `obj1`. At first `obj1`
// was just `{}`. The `[[prototype]]` property of `obj1` was then set to the current
// object value of the `ObjMaker.prototype` (if `ObjMaker.prototype` is later
// assigned a new object value, `obj1`'s `[[prototype]]` will not change, but you
// can alter the properties of `ObjMaker.prototype` to add to both the
// `prototype` and `[[prototype]]`). The `ObjMaker` function was executed, with
// `obj1` in place of `this`... so `obj1.a` was set to 'first'.
obj1.a;
// returns 'first'
obj1.b;
// `obj1` doesn't have a property called 'b', so JavaScript checks
// its `[[prototype]]`. Its `[[prototype]]` is the same as `ObjMaker.prototype`
// `ObjMaker.prototype` has a property called 'b' with value 'second'
// returns 'second'
这就像类继承,因为现在,您使用的任何对象new ObjMaker()
似乎也继承了“b”属性。
如果你想要类似子类的东西,那么你可以这样做:
SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);
SubObjMaker.prototype.c = 'third';
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype
obj2.c;
// returns 'third', from SubObjMaker.prototype
obj2.b;
// returns 'second', from ObjMaker.prototype
obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype
// was created with the ObjMaker function, which assigned a for us
我读了很多关于这个主题的垃圾,最后发现这一页 http://joost.zeekat.nl/constructors-considered-mildly-confusing.html,其中用漂亮的图表很好地解释了这一点。