如何創(chuàng)建JavaScript Object呢?有如下幾種方法:
一、Constructor Pattern
?
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function() { return this.name; } }; var p1 = new Person('Nicolas', 29, 'Software Engineer'); var p2 = new Person('Greg', 27, 'Doctor'); //function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function () {return this.name;}; } println(1, Person.toString()); println(2, Person.length);//3 println(3, Person.constructor);//function Function() { [native code] } println(4, Person.prototype.constructor == Person);//1 true; println(5, Person.prototype.name);//undefined; println(6, Person.prototype.age);//undefined; println(6, Person.prototype.job);//undefined; println(7, Person.prototype.sayName);//undefined; println(8, Person.prototype == p1.__proto__);//2 true; println(9, p2.__proto__ == p1.__proto__);//2 true; println(10, p2.sayName);//function(){return this.name); println(11, p2.sayName());//Greg println(10, p1.sayName);//function(){return this.name); println(11, p1.sayName());//Nicolas println(11, p2.sayName == p1.sayName);//false function println(i, value) { document.write(i + ' ' + value + '<hr/>'); }
?
?
注意:
1. 當(dāng)JavaScript解析從第一行~第九行的代碼的時候,發(fā)現(xiàn)時一段function聲明代碼的時候,會做如下幾個工作
A1:在heap里面生成一個Function對象代表這段function代碼
A2:給這個Function對象,這個對象會自動獲得一個prototype的屬性。這個屬性指向該對象的prototype object。默認(rèn)說來,所有的prototype object都會自動獲得一個constructor的屬性,該屬性存放指向Function對象的pointer
A3:設(shè)定這個Function的名字(因?yàn)檫@里不是一個匿名function)
A4:在global object對象建立Person的屬性,這個屬性的值為指向Function對象的指針。
?
2. 第11行:var p1 = new Person('Nicolas', 29, 'Software Engineer'),這里function作為new的方式呼叫,javascript是如何處理的呢?
A1:首先在heap去new Object,然后以這個Object作為這段code的execute context,加入到scope chain的頭部。此時this-->這個object,然后進(jìn)入code
A2:this.name = name,this.age = age,this.job=job,這三段代碼,對剛才生成的那個Object添加屬性,并賦值
A3:this.sayName = function(){...},這段會首先在heap里面生成一個function的對象,然后將該對象的pointer賦給剛才生成對象的sayName屬性上
A4:對這個object.__proto__賦值,指向function Person(name,age,job){...},然后將這個object的pointer賦值給stack里面的p1;(注意這個__proto__屬性,可以在firefox,safari,chrome等瀏覽器可以訪問,但在ie等瀏覽器則不能訪問,這是因?yàn)閷?shí)現(xiàn)EMCScript 262的規(guī)范不同造成的)
?
?
3.第30行的輸出結(jié)果是false,為什么呢?
從上面的分析,我們可以知道在new Person的時候,執(zhí)行this.sayName=function(){...},會首先去heap里面new Function Object,然后賦值給sayName,所以在p1和p2都會執(zhí)行這個過程。這樣就會new 2個邏輯上相等的Function Object,但是由于他們的內(nèi)存位置不同,所以在p1.sayName == p2.sayName的結(jié)果為false。這也是Contructor Pattern方式最大的問題,需要產(chǎn)生的Function Object太多了。
?
其內(nèi)存結(jié)構(gòu)為:
?
請參看代碼:
function Person() { }; //Person是一個Function的對象 Person.prototype.name = 'Nicolas'; Person.prototype.age = 29 Person.prototype.sayName = function() { return this.name; }; var p1 = new Person(); var p2 = new Person(); println(1, Person.toString()); println(2, Person.length); println(3, Person.constructor); println(4, Person.prototype.constructor == Person);//1 true; println(5, Person.prototype.name);//Nicolas; println(6, Person.prototype.name == p2.name);//Nicolas; println(7, Person.prototype.sayName == p2.sayName);//Nicolas; println(8, Person.prototype == p1.__proto__);//2 true; println(9, p2.__proto__ == p1.__proto__);//2 true; println(10, p2.__proto__.sayName == p1.__proto__.sayName); println(11, p2.sayName() == 'Nicolas'); println(12, p1.sayName == p1.sayName); println(13, p2.sayName() == p1.sayName()); function println(i, value) { document.write(i + ' ' + value + '<hr/>'); }
?
?注意:
這里是將property和method都加到Person.prototype所指向的prototype的對象上,因?yàn)閜1和p2都指向這個prototype對象的指針,所以訪問的時候,他們共享同一片內(nèi)存區(qū)域。對于方法而言是共享了,但是property卻混淆在了一塊兒。參看如下的內(nèi)存圖:
?
?
?
?
?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
