摘要:中有基本類型和復(fù)雜類型的區(qū)分。原型與原型鏈這里,就引入了兩個(gè)新的概念。原型對(duì)象就是用來存放聲明對(duì)象中共有的那部分屬性。而原型對(duì)象自身也是一個(gè)對(duì)象,它也有自己的原型對(duì)象。這樣層層上溯,就形成了一個(gè)類似鏈表的結(jié)構(gòu),這就是原型鏈。
JavaScript中有基本類型和復(fù)雜類型的區(qū)分。
當(dāng)我們?cè)诼暶饕粋€(gè)基本類型時(shí):
var n1= 1; console.log(n1); //1
這時(shí)我們可以用Number方法將1包裝為對(duì)象,即聲明一個(gè)對(duì)象1。
var n2= new Number(1); console.log(n2); //Number {1} //[[PrimitiveValue]]:1 //△__proto__: Number //constructor: ? Number() //toExponential: ? toExponential() //toFixed: ? toFixed() //toLocaleString: ? toLocaleString() //toPrecision: ? toPrecision() //toString: ? toString() //valueOf: ? valueOf() //__proto__: Object
n2的PrimitiveValue(初始值)為1,其實(shí)此時(shí)它就是一個(gè)hash。
此時(shí)對(duì)象n2現(xiàn)在有很多方法,可以調(diào)用對(duì)應(yīng)各自的函數(shù)。
但是,我們發(fā)現(xiàn)有一點(diǎn):在我們直接聲明基本數(shù)據(jù)類型n1時(shí),也可以使用這些方法調(diào)用函數(shù)。
比如toString方法:
var n1= 1; n1.toString(); //"1"
這就要涉及到JavaScript的發(fā)明歷史。在設(shè)計(jì)之初,它被要求:“長得像” Java。
當(dāng)時(shí)的Java聲明一個(gè)對(duì)象,就是如此:
var n= new Number(1)
設(shè)計(jì)師在設(shè)計(jì)的同時(shí),為了簡(jiǎn)便快捷,也制定了我們最常用的聲明方式:
var n= 1
當(dāng)然,這種方法肯定被JavaScript程序員所喜愛,第一種方法幾乎沒有人用。
但是有一個(gè)問題,如果直接聲明n,那么它就是一個(gè)數(shù)字。而基本數(shù)據(jù)類型是沒有屬性的。
這時(shí)候該如何調(diào)取各種方法呢?
聲明一個(gè)臨時(shí)對(duì)象,我們暫將它稱為temp。
比如在對(duì)n進(jìn)行toString方法引用時(shí),會(huì)聲明一個(gè)臨時(shí)對(duì)象,對(duì)n進(jìn)行復(fù)雜封裝,將其變?yōu)閷?duì)象。
var n= 1; n.toString();
其實(shí)是:
var temp= new Number(n); temp.toString(); //1
將temp.toString的值賦予n.toString。在操作結(jié)束后,臨時(shí)對(duì)象將從內(nèi)存中抹除。
共用屬性number,string,boolean,object都有一些共同的方法,比如toString,valueof等等。為了避免重復(fù)聲明和內(nèi)存浪費(fèi),這些方法“歸納”與一個(gè)共用屬性之中。
JavaScript在聲明一個(gè)對(duì)象后,并不是先默認(rèn)復(fù)制一遍共用屬性在內(nèi)存中的存放地址,再在引用時(shí)調(diào)取對(duì)應(yīng)的函數(shù)。而是:
在聲明對(duì)象時(shí),就存入一個(gè)隱藏的屬性:__proto__。該屬性,對(duì)應(yīng)其共用屬性。
var obj= { name: "Jack", age: 18 }; console.log(obj); //△{name:"Jack", age:18} //age: 18 //name: "Jack" //△__proto__: Object //constructor: ? Object() //hasOwnProperty: ? hasOwnProperty() //isPrototypeOf: ? isPrototypeOf() //propertyIsEnumerable: ? propertyIsEnumerable() //toLocaleString: ? toLocaleString() //toString: ? toString() //valueOf: ? valueOf() //__defineGetter__: ? __defineGetter__() //__defineSetter__: ? __defineSetter__() //__lookupGetter__: ? __lookupGetter__() //__lookupSetter__: ? __lookupSetter__() //get __proto__: ? __proto__() //set __proto__: ? __proto__()
那我們?cè)谡{(diào)用toString方法時(shí):
JavaScript首先會(huì)檢查數(shù)據(jù)類型是否是對(duì)象;若不是,則包裝為對(duì)象作臨時(shí)的轉(zhuǎn)換。
然后,在檢查對(duì)象中是否有toString這個(gè)屬性;若沒有,才進(jìn)入共用屬性進(jìn)行檢查。
兩個(gè)空對(duì)象是不相等的,但他們的共有屬性是相等的。
var obj1= {}; console.log(obj1); //{} var obj2= new Object(); console.log(obj2); //{} obj1 === obj2; //false obj1.__proto__ === obj2.__proto__; //true
但是,當(dāng)我們聲明一個(gè)number為對(duì)象時(shí),它就有自己區(qū)別于普通對(duì)象的獨(dú)特的共有屬性。
比如toFixed,toExponential等等。
那么它的__proto__屬性就對(duì)應(yīng)自己獨(dú)有的共同屬性,在共同屬性中還有另一個(gè)隱藏屬性__proto__對(duì)應(yīng)一般對(duì)象的共有屬性。這樣,number類型的對(duì)象就可以調(diào)用所有的函數(shù)。
這里,就引入了兩個(gè)新的概念。
那么,這個(gè)共有屬性,就被稱為原型(對(duì)象)。原型對(duì)象就是用來存放聲明對(duì)象中共有的那部分屬性。
JavaScript中所有的對(duì)象都可以繼承其原型對(duì)象的屬性。
而原型對(duì)象自身也是一個(gè)對(duì)象,它也有自己的原型對(duì)象。這樣層層上溯,就形成了一個(gè)類似鏈表的結(jié)構(gòu),這就是原型鏈。
為了避免對(duì)原型對(duì)象在沒有被使用時(shí)被內(nèi)存清理,JavaScript通過prototype來默認(rèn)引用。
Object.prototype
Object.prototype; //constructor: ? Object() //hasOwnProperty: ? hasOwnProperty() //isPrototypeOf: ? isPrototypeOf() //propertyIsEnumerable: ? propertyIsEnumerable() //toLocaleString: ? toLocaleString() //toString: ? toString() //valueOf: ? valueOf() //__defineGetter__: ? __defineGetter__() //__defineSetter__: ? __defineSetter__() //__lookupGetter__: ? __lookupGetter__() //__lookupSetter__: ? __lookupSetter__() //get __proto__: ? __proto__() //set __proto__: ? __proto__()
Number.prototype
Number.prototype; //constructor: ? Number() //toExponential: ? toExponential() //toFixed: ? toFixed() //toLocaleString: ? toLocaleString() //toPrecision: ? toPrecision() //toString: ? toString() //valueOf: ? valueOf() //__proto__: Object //[[PrimitiveValue]]: 0
如此,還有:
String.prototype
Boolean.prototype
等等。
Object.prototype.__proto__ === null
我們制作一個(gè)簡(jiǎn)單的示意圖,以便更直觀地理解這些概念。
那么我們可以得到關(guān)系:
var obj= {}; obj.__proto__ === Object.prototype; //true var n= new Number(1); n.__proto__ === Number.prototype; //true n.__proto__.__proto__ === Object.prototype; //true總結(jié)起來,得到的結(jié)論就是:
Object.prototype是Object的共用屬性
obj.__proto__是Object的共用屬性的引用
同理,對(duì)于String、Boolean、Symbol和Number也是如此
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/100235.html
摘要:在中,主要有兩種創(chuàng)建對(duì)象的方法分別是對(duì)象字面量以及調(diào)用構(gòu)造函數(shù)對(duì)象字面量調(diào)用構(gòu)造函數(shù)其實(shí)上述兩種創(chuàng)建對(duì)象的方法,本質(zhì)上是一樣的,都是引擎調(diào)用對(duì)象的構(gòu)造函數(shù)來新建出一個(gè)對(duì)象。 原型與原型鏈?zhǔn)莏avascript里面最最核心的內(nèi)容,如果不能理解它們之間的存在關(guān)系的話,那么我們是不能理解這門語言的。 在JS中,主要有兩種創(chuàng)建對(duì)象的方法, 分別是對(duì)象字面量以及調(diào)用構(gòu)造函數(shù) //對(duì)象字面量 va...
摘要:在講原型之前,先簡(jiǎn)單介紹一下幾個(gè)概念構(gòu)造函數(shù)例如上述代碼創(chuàng)建的函數(shù)就被稱為構(gòu)造函數(shù)。同一個(gè)構(gòu)造函數(shù)實(shí)例化得到的多個(gè)對(duì)象具有相同的原型對(duì)象,所以經(jīng)常使用原型對(duì)象來實(shí)現(xiàn)繼承。實(shí)例對(duì)象通過操作構(gòu)造函數(shù)所創(chuàng)建的對(duì)象是實(shí)例對(duì)象。 對(duì)于很多前端開發(fā)者而言,JavaScript的原型實(shí)在是很讓人頭疼,所以我這邊就整理了一下自己對(duì)應(yīng)原型的一點(diǎn)理解,分享給大家,供交流使用 原型 說起原型,那就不得不說p...
摘要:在講原型之前,先簡(jiǎn)單介紹一下幾個(gè)概念構(gòu)造函數(shù)例如上述代碼創(chuàng)建的函數(shù)就被稱為構(gòu)造函數(shù)。同一個(gè)構(gòu)造函數(shù)實(shí)例化得到的多個(gè)對(duì)象具有相同的原型對(duì)象,所以經(jīng)常使用原型對(duì)象來實(shí)現(xiàn)繼承。實(shí)例對(duì)象通過操作構(gòu)造函數(shù)所創(chuàng)建的對(duì)象是實(shí)例對(duì)象。 對(duì)于很多前端開發(fā)者而言,JavaScript的原型實(shí)在是很讓人頭疼,所以我這邊就整理了一下自己對(duì)應(yīng)原型的一點(diǎn)理解,分享給大家,供交流使用 原型 說起原型,那就不得不說p...
摘要:我們通過這個(gè)構(gòu)造函數(shù)為原型對(duì)象添加其他方法和屬性。這個(gè)屬性存在與實(shí)例與構(gòu)造函數(shù)的原型對(duì)象上直接,而不存在于實(shí)例與構(gòu)造函數(shù)之間。李小花班花張全蛋張全蛋李小花李小花我們?cè)诒闅v對(duì)象的的屬性的時(shí)候,經(jīng)常需要判斷屬性是否來自于對(duì)象的原型還是屬性。 引言 上面說了創(chuàng)建對(duì)象有字面量方式和工廠模式還有構(gòu)造函數(shù)模式,結(jié)果發(fā)現(xiàn)他們都各自有缺點(diǎn),所以下面再給大家介紹幾種創(chuàng)建對(duì)象的方式,爭(zhēng)取能找到一種無痛的模...
閱讀 1324·2021-11-24 10:24
閱讀 4167·2021-11-22 15:29
閱讀 1101·2019-08-30 15:53
閱讀 2801·2019-08-30 10:54
閱讀 1988·2019-08-29 17:26
閱讀 1293·2019-08-29 17:08
閱讀 613·2019-08-28 17:55
閱讀 1591·2019-08-26 14:01