參考 http://aralejs.org/class/docs/competitors.html, http://www.iteye.com/topic/248933,http://www.cnblogs.com/qiantuwuliang/archive/2011/01/08/1930548.htmljavascript
一、使用Dog.prototype.__proto__ html
function Animal() {} function Dog() {} // 要讓 Dog 繼承 Animal, 只需: Dog.prototype.__proto__ == Animal.prototype; // 實例化後 var dog = new Dog(); // dog.__proto__ 指向 Dog.prototype // dog.__proto__.__proto__ 指向 Animal.prototype // 原型鏈已成功創建起來,並且很清晰
function Animal(name) { this.name = name; } Animal.prototype = { talk: function() {}, run: function() {} } function Dog(age,name) { //Animal.call(this,name) this.age=age; } // 要讓 Dog 繼承 Animal, 只需:__ 2個_ Dog.prototype.__proto__ = Animal.prototype ; // 實例化後 //Dog.prototype = new Animal ; //Animal的構造函數和本身的prototype也都放到Dog上 Dog.prototype.haha = function () {};// Dog.prototype.haha.tata = 4; var dog = new Dog("sdd","bbb"); var animal = new Animal("aaaa"); console.log(dog); console.log(Dog.prototype); console.log(animal.__proto__); console.log("11 "+(dog instanceof Animal)); console.log("11 "+(animal instanceof Dog));
__proto__指向了dog自己,而且有constructor,開始循環引用了。dog.__proto__=Dog.prototype。java
dog自己的Dog.prototype沒有被覆蓋,一個標準的prototype,包括constructor和__proto__,咱們只覆蓋了這個標準的prototype的__proto__而已。chrome
若是不加__proto__ 函數
function Animal(name) { this.name = name; } Animal.prototype = { talk: function() {}, run: function() {} } function Dog(name) { Animal.call(this,name) } // 要讓 Dog 繼承 Animal, 只需: Dog.prototype = Animal.prototype; // 實例化後 var dog = new Dog("sdd"); console.log(dog);
返回this
第二種原型鏈沒有創建,沒有constructor,只是簡單的把方法賦值過來了。上面用 console.log(dog instanceof Animal ) 都返回ture。spa
function Animal(name) { this.name = name; } Animal.prototype = { talk: function() {}, run: function() {} } function Dog(name) { Animal.call(this,name) } // 要讓 Dog 繼承 Animal, 只需: Dog.prototype = Animal.prototype;//有沒有有__proto__都會被覆蓋 Dog.prototype = { qqq: function() {}, wwww: function() {} } // 實例化後 var dog = new Dog("sdd"); console.log(dog); console.log(dog instanceof Animal );
Dog {name: "sdd", qqq: function, wwww: function} name: "sdd" __proto__: Object qqq: function () {} wwww: function () {} __proto__: Object
Dog.prototype被覆蓋了,自己的constructor和__proto__不存在了,變 Animal.prototype了。prototype
2,使用newcode
function Animal(name) { this.name = name; } Animal.prototype = { talk: function() {}, run: function() {} } function Dog(age,name) { //Animal.call(this,name) this.age=age; } // 要讓 Dog 繼承 Animal, 只需:__ 2個_ //Dog.prototype.__proto__ = Animal.prototype ; // 實例化後 Dog.prototype = new Animal ; //Animal的構造函數和本身的prototype也都放到Dog上 Dog.prototype.haha = function () {}; var dog = new Dog("sdd","bbb"); var animal = new Animal("aaaa"); console.log(dog); console.log(dog.__proto__); console.log(animal.__proto__); console.log(dog.__proto__===Dog.prototype);
Dog {age: "sdd", name: undefined, haha: function, talk: function, run: function} age: "sdd" __proto__: Animal haha: function () {} name: undefined __proto__: Object run: function () {} talk: function () {} __proto__: Object
new 是調用構造函數的,會把構造函數上的屬性拿過來,沒有constructor,只有new 帶構造函數。__proto__是實例化後纔有,他表明的原型鏈,能夠共享的原型鏈,上圖中方法haha 也放到__proto__中了。orm
Dog.prototype被覆蓋了,自己的constructor和__proto__不存在了,變 new Animal了,因而構造函數都傳過來了。
沒有繼承的狀況下,以下圖所示,prototype沒有被覆蓋,constructor保留,是Dog自己這個函數。dog.constructor === Dog.prototype.constructor
function Dog(age,name) { //Animal.call(this,name) this.age=age; this.getName = function (){}; } var dog = new Dog("sdd","bbb"); console.log(dog); //結果 Dog {age: "sdd", getName: function} age: "sdd" getName: function (){} __proto__: Dog constructor: function Dog(age,name) { __proto__: Object
constructor: function Dog(age,name) { arguments: null caller: null length: 2 name: "Dog" prototype: Dog __proto__: function Empty() {} <function scope>
按照《悟透javascript》書中說的,new形式建立對象的過程實際上能夠分爲三步:
第一步是創建一個新對象(叫A吧);
第二步將該對象(A)內置的原型對象設置爲構造函數(就是Person)prototype 屬性引用的那個原型對象;
第三步就是將該對象(A)做爲this 參數調用構造函數(就是Person),完成成員設置等初始化工做。
其中第二步中出現了一個新名詞就是內置的原型對象,注意這個新名詞跟prototype對象不是一回事,爲了區別我叫它inobj,inobj就指向了函數Person的prototype對象。在person的prototype對象中出現的任何屬性或者函數均可以在one對象中直接使用,這個就是javascript中的原型繼承了。
總結: 1)Dog.prototype = Animal.prototype 或者Dog.prototype.__proto__ = Animal.prototype 時,dog instanceof Animal 都是true。Dog.prototype.__proto__ = Animal.prototype,實際實例化後是 dog.__proto__.__proto__=Animal.prototype。沿着A的原型鏈查找 若是有一個原型和B.prototype相等 則返回true , 如:A.__proto__.__proto__ === B.prototype 則返回true
js的 instanceof 是根據什麼來判斷兩個對象的繼承關係?參考:http://yxc-gdut.iteye.com/blog/1812766
js的instanceof是根據prototype來判斷兩個對象是否存在繼承關係,A instanceof B, js會沿着A的原型鏈查找 直到找到A.__proto__ === B.prototype 返回true。
一句話__proto__一層層都是指向繼承的,最終到基本類型上。沒有繼承的就是他的protoype,包含constructor: function () {},__proto__: Object,和他本身加的方法。
下圖展現的new方法的,Dog.prototype = new Animal ;因此dog第一層__proto__有name, new把構造函數有傳入了。只有有prototype chrome下才能展現出來下面的結構。
Dog {age: "sdd", name: undefined, haha: function, talk: function, run: function} age: "sdd" __proto__: Animal haha: function () {} name: undefined __proto__: Object run: function () {} talk: function () {} __proto__: Object
2)理解下function ,以下圖。function ,包括 arguments, caller,length,name ,prototype,__proto__,他的prototype,又分爲constructor: function () {},__proto__: Object,而後constructor這個function 又繼續循環。
__proto__他從別的原型鏈繼承過來能夠直接用的,prototype是他要加在本身原型鏈上的,供別人調用,或者直接實例化後,別人能夠直接調用轉成__proto__的。
run: function () {} arguments: null caller: null length: 0 name: "" prototype: Object constructor: function () {} __proto__: Object __proto__: function Empty() {}
var AAA= function(name) { this.name=222; } AAA.dhj="123"; AAA.prototype.www=function(){}; var aaa=new AAA(); console.log(aaa);
有繼承關係的__proto__他指向的是指定的繼承的那個,沒有繼承關係的__proto__依然保留constructor: function () {},__proto__: Object。
AAA {name: 222, www: function} name: 222 __proto__: Object constructor: function (name) { www: function (){} __proto__: Object
按照javascript的說法,function定義的這個是一個Object(對象),並且仍是一個很特殊的對象,這個使用function定義的對象與使用new操做符生成的對象之間有一個重要的區別。這個區別就是function定義的對象有一個prototype屬性,使用new生成的對象就沒有這個prototype屬性。prototype屬性又指向了一個prototype對象,注意prototype屬性與prototype對象是兩個不一樣的東西,要注意區別。在prototype對象中又有一個constructor屬性,這個constructor屬性一樣指向一個constructor對象,而這個constructor對象偏偏就是這個function函數自己。
下面分析下constructor
function Animal(name) { this.name = name; var a=1; } Animal.prototype.talk=function(){}; var animal = new Animal("aaaa"); function Dog(age,name) { //Animal.call(this,name) this.age=age; this.getName = function (){}; } // 要讓 Dog 繼承 Animal, 只需:__ 2個_ //Dog.prototype.__proto__ = Animal.prototype ; // 實例化後 Dog.prototype = animal ; //注意這裏啊, Dog.prototype.constructor = Dog;//animal自己也有constructor,animal自己也指定到這裏。引用傳遞。animal已經實例化了
var dog = new Dog("sdd","bbb"); console.log(dog); console.log(dog.constructor);; console.log(animal); console.log(animal.constructor);
Dog {age: "sdd", getName: function, name: "aaaa", constructor: function, talk: function} age: "sdd" getName: function (){} __proto__: Animal function Dog(age,name) { //Animal.call(this,name) this.age=age; this.getName = function (){}; } Animal {name: "aaaa", constructor: function, talk: function} constructor: function Dog(age,name) { name: "aaaa" __proto__: Animal function Dog(age,name) { //Animal.call(this,name) this.age=age; this.getName = function (){}; }