问题已解决,使用function的是道式的原型继承法,其本质就是构造一个只有__proto__属性的对象,所以才有我的第二种改法。至于第三种改法,已证明是错误的。
最近在看原型继承的方面的文章,举例一个子类继承父类的(已去除constructor修正和call构造)
var F = function() {}; F.prototype = SuperClass.prototype; SubClass.prototype = new F();
思考其本质,其实就是构造一个最纯粹的对象作为子类的原型,那么我完全可以这么写
var F = {}; F.__proto__ = SuperClass.prototype; SubClass.prototype = F;
可能有人会说__proto__属性按照标准不该直接设置,所以才使用的道格拉斯文中的过度函数式构造法,那么再修改下,改为prototype也是一样的。
var F = {}; F.prototype = SuperClass.prototype SubClass.prototype = F;
可以看到__proto__和prototype均可用作原形链的查找,那么他们两的区别是啥,对象中同时存在这两个属性的话,原形链又是怎么查的,遍历顺序?
好吧,问完这个问题我又检查了测试程序,原来最后一种是不行的,附上代码如下。尝试修改继承方法为type1/type2/type3,发现type2报错了。如前文所说直接修改__proto__不好,所以还是用道式的原型对象构造法吧。果然js内部进行原形链查找只用__proto__,在new实例化对象的时候,对象的__proto__就指向了定义时的prototype,有点感觉像是linux中用户层对象对应于内核层某个对象的感觉。
function type1() { var F = {}; F.__proto__ = Car.prototype; return F; } function type2() { var F = {}; F.prototype = Car.prototype; return F; } function type3() { var F2 = function() {}; F2.prototype = Car.prototype; return new F2(); } Car = function () { this.type = 'car'; }; Car.prototype = { getPrice: function () { console.log('not initial'); }, getSpeed: function () { console.log('not initial'); } }; var BMW = function (price, speed) { Car.call(this); this.price = price; this.speed = speed; }; BMW.prototype = type3(); var bmw = new BMW(1000000, 100); bmw.getPrice(); bmw.getSpeed();
_proto_
是所有对象(包括函数)都有的,它才叫做对象的原型,原型链就是靠它形成的。prototype
只有函数(准确地说是构造函数)才有的。它跟原型链没有半毛钱关系。它的作用是:构造函数new对象的时候,告诉构造函数新创建的对象的原型是谁。是的,只在new一个对象的时候才起作用。当你new完得到这个对象后,随便你怎么改构造函数的prototype
属性,都不会影响已创建的对象的原型链。另外,你问题中给一个对象设置
prototype
属性的代码是让人费解的。对象不应该设置prototype
属性。一个是函数的,一个是对象的。。。
prototype是构造函数用的,构造函数构造的对象的__proto__属性将会等于构造函数的prototype,函数前面加new关键字那么这个函数是构造函数,否则prototype没什么卵用
这里http://varnull.cn/cong-__prot...是我对原型链的理解,可以交流哈