摘要:接下解釋和屬性同樣拿上面的代碼來解釋輸出首先給構造函數的原型對象賦給方法,由構造函數創建的實例會繼承原型對象上的方法。
本文為了解決以下問題:
__proto__(實際原型)和prototype(原型屬性)不一樣!!!
constructor屬性(原型對象中包含這個屬性,實例當中也同樣會繼承這個屬性)
prototype屬性(constructor.prototype原型對象)
__proto__屬性(實例指向原型對象的指針)
首先弄清楚幾個概念:
什么是對象若干屬性的集合
什么是原型?原型是一個對象,其他對象可以通過它實現繼承。
哪些對象有原型?所有的對象在默認情況下都有一個原型,因為原型本身也是對象,所以每個原型自身又有一個原型(只有一種例外,默認的對象原型在原型鏈的頂端)
任何一個對象都可以成為原型接下來就是最核心的內容:
constructor 屬性constructor屬性始終指向創建當前對象的構造函數。
var arr=[1,2,3]; console.log(arr.constructor); //輸出 function Array(){} var a={}; console.log(arr.constructor);//輸出 function Object(){} var bool=false; console.log(bool.constructor);//輸出 function Boolean(){} var name="hello"; console.log(name.constructor);//輸出 function String(){} var sayName=function(){} console.log(sayName.constrctor)// 輸出 function Function(){} //接下來通過構造函數創建instance function A(){} var a=new A(); console.log(a.constructor); //輸出 function A(){}
以上部分即解釋了任何一個對象都有constructor屬性,指向創建這個對象的構造函數
prototype屬性注意:prototype是每個函數對象都具有的屬性,被稱為原型對象,而__proto__屬性才是每個對象才有的屬性。一旦原型對象被賦予屬性和方法,那么由相應的構造函數創建的實例會繼承prototype上的屬性和方法
//constructor : A //instance : a function A(){} var a=new A(); A.prototype.name="xl"; A.prototype.sayName=function(){ console.log(this.name); } console.log(a.name);// "xl" a.sayName();// "xl" //那么由constructor創建的instance會繼承prototype上的屬性和方法constructor屬性和prototype屬性
每個函數都有prototype屬性,而這個prototype的constructor屬性會指向這個函數。
function Person(name){ this.name=name; } Person.prototype.sayName=function(){ console.log(this.name); } var person=new Person("xl"); console.log(person.constructor); //輸出 function Person(){} console.log(Person.prototype.constructor);//輸出 function Person(){} console.log(Person.constructor); //輸出 function Function(){}
如果我們重寫(重新定義)這個Person.prototype屬性,那么constructor屬性的指向就會發生改變了。
Person.prototype={ sayName:function(){ console.log(this.name); } } console.log(person.constructor==Person); //輸出 false (這里為什么會輸出false后面會講) console.log(Person.constructor==Person); //輸出 false console.log(Person.prototype.constructor);// 輸出 function Object(){} //這里為什么會輸出function Object(){} //還記得之前說過constructor屬性始終指向創建這個對象的構造函數嗎? Person.prototype={ sayName:function(){ console.log(this.name); } } //這里實際上是對原型對象的重寫: Person.prototype=new Object(){ sayName:function(){ console.log(this.name); } } //看到了吧。現在Person.prototype.constructor屬性實際上是指向Object的。 //那么我如何能將constructor屬性再次指向Person呢? Person.prototype.constructor=Person;
接下來解釋為什么,看下面的例子
function Person(name){ this.name = name; } var personOne=new Person("xl"); Person.prototype = { sayName: function(){ console.log(this.name); } }; var personTwo = new Person("XL"); console.log(personOne.constructor == Person); //輸出true console.log(personTwo.constructor == Person); //輸出false //大家可能會對這個地方產生疑惑?為何會第二個會輸出false,personTwo不也是由Person創建的嗎?這個地方應該要輸出true啊? //這里就涉及到了JS里面的原型繼承 //這個地方是因為person實例繼承了Person.prototype原型對象的所有的方法和屬性,包括constructor屬性。當Person.prototype的constructor發生變化的時候,相應的person實例上的constructor屬性也會發生變化。所以第二個會輸出false; //當然第一個是輸出true,因為改變構造函數的prototype屬性是在personOne被創建出來之后。
接下解釋__proto__和prototype屬性
同樣拿上面的代碼來解釋:
function Person(name){ this.name=name; } Person.prototype.sayName=function(){ console.log(this.name); } var person=new Person("xl"); person.sayName(); //輸出 "xl" //constructor : Person //instance : person //prototype : Person.prototype
首先給構造函數的原型對象Person.prototype賦給sayName方法,由構造函數Person創建的實例person會繼承原型對象上的sayName方法。
為什么會繼承原型對象的方法?因為ECMAscript的發明者為了簡化這門語言,同時又保持繼承性,采用了鏈式繼承的方法。
由constructor創建的每個instance都有個__proto__屬性,它指向constructor.prototype。那么constrcutor.prototype上定義的屬性和方法都會被instance所繼承.
function Person(name){ this.name=name; } Person.prototype.sayName=function(){ console.log(this.name); } var personOne=new Person("a"); var personTwo=new Person("b"); personOne.sayName(); // 輸出 "a" personTwo.sayName(); //輸出 "b" console.log(personOne.__proto__==Person.prototype); // true console.log(personTwo.__proto__==Person.prototype); // true console.log(personOne.constructor==Person); //true console.log(personTwo.constructor==Person); //true console.log(Person.prototype.constructor==Person); //true console.log(Person.constructor); //function Function(){} console.log(Person.__proto__.__proto__); // Object{}
參考文章:
強大的原型和原型鏈
js原型鏈看圖說明
理解javascript原型
javascript類和繼承:constructor
javascript探秘:構造函數
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85836.html
摘要:使用操作符,創建一個對象,并且執行構造函數方法。使用可以返回一個字典型對象對象原型每一個對象都有一個內置的屬性指向構造它的函數屬性而構造函數的則指向構造函數本生。 對象概念 在 javascript 中, 一切引用類型均為對象。 如 function Foo () {} 中,Foo本身就是一個對象的引用。 創建對象方式 字面量方式 new 構造函數 函數聲明 Object.creat...
摘要:二構造函數我們先復習一下構造函數的知識上面的例子中和都是的實例。這兩個實例都有一個構造函數屬性,該屬性是一個指針指向。原型鏈其中是對象的實例。 一. 普通對象與函數對象 JavaScript 中,萬物皆對象!但對象也是有區別的。分為普通對象和函數對象,Object 、Function 是 JS 自帶的函數對象。下面舉例說明 var o1 = {}; var o2 =new Objec...
摘要:原型對象內部也有一個指針屬性指向構造函數實例可以訪問原型對象上定義的屬性和方法。在創建子類型的實例時,不能向超類型的構造函數中傳遞參數。 贊助我以寫出更好的文章,give me a cup of coffee? 2017最新最全前端面試題 私有變量和函數 在函數內部定義的變量和函數,如果不對外提供接口,外部是無法訪問到的,也就是該函數的私有的變量和函數。 function ...
摘要:歡迎關注前端小謳的,閱讀更多原創技術文章用構造函數,生成對象實例使用構造函數,并且構造函數后臺會隱式執行創建對象將構造函數的作用域給新對象,即創建出的對象,函數體內的代表出來的對象執行構造函數的代碼返回新對象后臺直接返回用改寫上述代碼通過關 歡迎關注前端小謳的github,閱讀更多原創技術文章 用構造函數,生成對象實例: 使用構造函數,并且new 構造函數(), 后臺會隱式執行ne...
摘要:執行行代碼,我們可以看到控制臺打印出來的結果如下結果印證了我們上面講的內容指向的構造函數指向的原型對象原型對象中指向構造函數。 在javascript中原型和原型鏈機制是最難懂的部分(沒有之一),同時也是最重要的部分,在學習的過程中你可能認認真真的看了一遍但還是完全不懂書上說的什么,的確是這樣的,我在學習的時候可是反復看了4、5遍才初步理解了。 下面我把我的理解總結了一下希望對你們有...
閱讀 1871·2021-11-25 09:43
閱讀 3161·2021-11-15 11:38
閱讀 2708·2019-08-30 13:04
閱讀 483·2019-08-29 11:07
閱讀 1492·2019-08-26 18:37
閱讀 2697·2019-08-26 14:07
閱讀 583·2019-08-26 13:52
閱讀 2278·2019-08-26 12:09