摘要:于是退而求其次叫為類的構造函數。如果這個函數被用在創建自定義對象的場景中,我們稱這個函數為構造函數。遇到的問題始終指向創建當前對象的構造函數。
Object.constructor,prototype
對象的prototype和constructor是兩個重要的屬性,他們總是成對出現,提到constructor的地方,不得不涉及到另外一個非常重要的屬性prototype,它是js中基于原型繼承的一個基礎。所謂的成對出現,是因為function的prototype屬性指向了一個prototype對象,在prototype對象中又有一個constructor屬性,這個constructor屬性同樣指向一個constructor對象,而這個constructor對象恰恰就是這個function函數本身。
function Person(name) { this.name=name; this.showMe=function() { alert(this.name); } }; var one=new Person("JavaScript"); one.showMe();//JavaScript
很多人見到了久違的new操作符,于是就叫Person為“類”,可是又沒有關鍵字class的出現,覺得叫“類”有點勉強。于是退而求其次叫Person為類的構造函數。這些概念好像都沒有錯,之所以出現這樣的情況,可能是因為大家都學習了傳統的面向對象語言(c++,c#,java等),還有一種思維定勢吧。為了讓javascript也面向對象,要在javascript中找到與傳統面向對象語言的影子。可是按照javascript的說法,function定義的這個Person就是一個Object(對象),而且還是一個很特殊的對象,這個使用function定義的對象與使用new操作符生成的對象之間有一個重要的區別。
這個區別就是function定義的對象有一個prototype屬性,使用new生成的對象就沒有這個prototype屬性。(這個之前沒有注意過這個區別,代碼測試下竟然還真是)
function Person(name) { this.name=name; this.showMe=function() { alert(this.name); } }; var one=new Person("js"); alert(one.prototype)//undefined alert(typeof Person.prototype);//object alert(Person.prototype.constructor);//function Person(name) {...};
one這個對象竟然沒有prototype屬性。。。
function Person(name) { this.name=name; this.showMe=function() { alert(this.name); } }; Person.prototype.from=function() { alert("I come from prototype."); } var one=new Person("js"); one.showMe();//js,這個結果正常 one.from();//I come from prototype.,這個結果有一點奇怪
要解釋這個結果就要仔細研究一下new這個操作符了
var one=new Person("js");
這個語句執行的過程可以分成下面的語句:
var one={}; Person.call(one,"js");
按照《悟透javascript》書中說的,new形式創建對象的過程實際上可以分為三步:
第一步是建立一個新對象(叫A吧);
第二步將該對象(A)內置的原型對象設置為構造函數(就是Person)prototype 屬性引用的那個原型對象;
第三步就是將該對象(A)作為this 參數調用構造函數(就是Person),完成成員設置等初始化工作。
其中第二步中出現了一個新名詞就是內置的原型對象__prop__,注意這個新名詞跟prototype對象不是一回事,__prop__(圖中標記的inobj)就指向了函數Person的prototype對象。在person的prototype對象中出現的任何屬性或者函數都可以在one對象中直接使用,這個就是javascript中的原型繼承了。示意圖如下所示:
每個函數都有一個默認的prototype屬性。
如果這個函數被用在創建自定義對象的場景中,我們稱這個函數為構造函數。 比如下面一個簡單的例子:
// 構造函數 function Person(name) { this.name = name; } // 定義Person的原型,原型中的屬性可以被自定義對象引用 Person.prototype = { getName: function() { return this.name; } } var zhang = new Person("ZhangSan"); console.log(zhang.getName()); // "ZhangSan"
作為類比,我們考慮下JavaScript中的數據類型 - 字符串(String)、數字(Number)、數組(Array)、對象(Object)、日期(Date)等。
我們有理由相信,在JavaScript內部這些類型都是作為構造函數來實現的;
同時對數組操作的很多方法(比如concat、join、push)應該也是在prototype屬性中定義的。
實際上,JavaScript所有的固有數據類型都具有只讀的prototype屬性(因為如果修改了這些類型的prototype屬性,則哪些預定義的方法就消失了),但是我們可以向其中添加自己的擴展方法。
constructor始終指向創建當前對象的構造函數。
var arr = [1, 56, 34, 12];// 等價于 var foo = new Array(1, 56, 34, 12); console.log(arr.constructor === Array); // true var Foo = function() { }; // 等價于 var foo = new Function(); console.log(Foo.constructor === Function); // true // 由構造函數實例化一個obj對象 var obj = new Foo(); console.log(obj.constructor === Foo); // true // 將上面兩段代碼合起來,就得到下面的結論 console.log(obj.constructor.constructor === Function); // true
但是當constructor遇到prototype時,有趣的事情就發生了。 這個現象在我的這篇博客里基于原型創建對象的時候也提到過。鏈接描述
我們知道每個函數都有一個默認的屬性prototype,而這個prototype的constructor默認指向這個函數。如下例所示:
function Person(name) { this.name = name; }; Person.prototype.getName = function() { return this.name; }; var p = new Person("ZhangSan"); console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true // 將上兩行代碼合并就得到如下結果 console.log(p.constructor.prototype.constructor === Person); // true
當時當我們重新定義函數的prototype時(這里不是修改而是覆蓋),或者成為原型重寫,constructor的行為就有點奇怪了,如下示例:
function Person(name) { this.name = name; }; Person.prototype = { getName: function() { return this.name; } }; var p = new Person("ZhangSan"); console.log(p.constructor === Person); // false console.log(Person.prototype.constructor === Person); // false console.log(p.constructor.prototype.constructor === Person); // false
是因為覆蓋Person.prototype時,等價于進行如下代碼操作:
Person.prototype = new Object({ getName: function() { return this.name; } });
而constructor始終指向創建自身的構造函數,所以此時Person.prototype.constructor === Object,即:
function Person(name) { this.name = name; }; Person.prototype = { getName: function() { return this.name; } }; var p = new Person("ZhangSan"); console.log(p.constructor === Object); // true console.log(Person.prototype.constructor === Object); // true console.log(p.constructor.prototype.constructor === Object); // true
如何修正過來,只需要重新覆蓋Person.prototype.constructor即可:
function Person(name) { this.name = name; }; Person.prototype = new Object({ getName: function() { return this.name; } }); Person.prototype.constructor = Person; var p = new Person("ZhangSan"); console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true console.log(p.constructor.prototype.constructor === Person); // trueObject的常用方法
javascript中的一切皆對象,而這些對象的有一個最父層的類就是Object,常用的一些屬性方法匯總一下,這些方法在判斷上述問題以及其他方面很有用。
Object.constructor //對象的構造函數 Object.hasOwnProperty() //檢查對象屬性是否被繼承 Object.isPrototypeOf() //檢查一個對象是否是另外一個對象的原型 Object.propertyIsEnumerable() //是否可以通過for/in 循環看到屬性 Object.toLocaleString() //返回對象的本地字符串表示 Object.toString() //定義一個對象的字符串表示 Object.valueOf() //制定對象的原始值
最近從圖書館把那邊厚厚的《javascript高級程序設計》借過來了,看看單單事件就能將講那么厚厚一章,打算搞一個基礎知識系列~~求監督和共勉
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/86056.html
摘要:給添加屬性給的原型對象添加屬性原型鏈在中,每個對象都有一個屬性,其保存著的地址就構成了對象的原型鏈。實例變量實例函數原型鏈繼承有了原型鏈,就可以借助原型鏈實現繼承。是中唯一一個處理屬性但是不查找原型鏈的函數。 前端學習:教程&開發模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:原型&原型鏈&原型繼承 JavaScript-原...
我們在學習javascript時,經常會聽到萬物皆對象,但是呢,其實萬物皆對象的對象也有區別。分為普通對象和函數對象。1.對象分為函數對象和普通對象? ??通過new Function()創建的對象都是函數對象,其他的都是普通對象。showImg(https://segmentfault.com/img/bVbtWre?w=526&h=252); 2.構造函數而提到new關鍵字,我們不得不提到構造...
摘要:然而事實上并不是。函數本身也是一個對象,但是給這個對象添加屬性并不能影響。一圖勝千言作者給出的解決方案,沒有麻煩的,沒有虛偽的,沒有混淆視線的,原型鏈連接不再赤裸裸。所以是這樣的一個函數以為構造函數,為原型。 注意:本文章是個人《You Don’t Know JS》的讀書筆記。在看backbone源碼的時候看到這么一小段,看上去很小,其實忽略了也沒有太大理解的問題。但是不知道為什么,我...
摘要:基礎原型原型鏈構造函數默認有這一行張三李四構造函數擴展其實是的語法糖其實是的語法糖其實是使用判斷一個函數是否是一個變量的構造函數原型規則和示例所有的引用類型數組對象函數,都具有對象屬性即可自有擴展的屬性,除外所有的引用類型數組對象函數, JavaScript基礎 —— 原型&&原型鏈 構造函數 function Foo(name, age) { this.name = na...
摘要:而和的存在就是為了建立這種子類與父類間的聯系。創建一個基本對象建立新對象與原型我把它理解為類之間的連接執行構造函數小結可以理解為類,也就是存儲一類事物的基本信息。原型原型鏈和繼承之間的關系。 原型 原型的背景 首先,你應該知道javascript是一門面向對象語言。 是對象,就具有繼承性。 繼承性,就是子類自動共享父類的數據結構和方法機制。 而prototype 和 __proto__...
閱讀 1027·2021-09-26 09:55
閱讀 3574·2021-09-24 10:30
閱讀 1374·2021-09-08 09:36
閱讀 2558·2021-09-07 09:58
閱讀 609·2019-08-30 15:56
閱讀 774·2019-08-29 18:32
閱讀 3622·2019-08-29 15:13
閱讀 1847·2019-08-29 13:49