摘要:但是確是一個(gè)特例它的指向的是至于為什么簡(jiǎn)單解釋下所有的構(gòu)造器都來(lái)自于,甚至包括根構(gòu)造器及自身。所有構(gòu)造器都繼承了的屬性及方法。如知道了所有構(gòu)造器含內(nèi)置及自定義的都是,的是誰(shuí)呢這說(shuō)明所有的構(gòu)造器也都是一個(gè)普通對(duì)象,可以給構(gòu)造器添加刪除屬性等。
前言
此文章為加深對(duì)JS中重要概念進(jìn)行理解,不建議沒(méi)有任何JS基礎(chǔ)的人看,只為加深對(duì)概念理解通過(guò)實(shí)際的例子,而不是看書(shū)以為自己讀懂了,可能幾天后就忘了,主要是為了理解核心概念,以及對(duì)重難點(diǎn)解釋。
一切都是對(duì)象概念“一切都是對(duì)象”這句話的重點(diǎn)在于如何去理解“對(duì)象”這個(gè)概念。
JavaScript 中,萬(wàn)物皆對(duì)象!但對(duì)象也是有區(qū)別的。分為普通對(duì)象和函數(shù)對(duì)象,Object 、Function 是 JS 自帶的函數(shù)對(duì)象。
當(dāng)然,也不是所有的都是對(duì)象,值類型就不是對(duì)象。
function show(x) { console.log(typeof x); // undefined console.log(typeof 10); // number console.log(typeof "abc"); // string console.log(typeof true); // boolean console.log(typeof function () {}); //function console.log(typeof [1, "a", true]); //object console.log(typeof { a: 10, b: 20 }); //object console.log(typeof null); //object console.log(typeof new Number(10)); //object } show();
以上代碼列出了typeof輸出的集中類型標(biāo)識(shí),其中上面的四種(undefined, number, string, boolean)屬于簡(jiǎn)單的值類型,不是對(duì)象。剩下的幾種情況——函數(shù)、數(shù)組、對(duì)象、null、new Number(10)都是對(duì)象。他們都是引用類型。
對(duì)象——若干屬性的集合 概念數(shù)組是對(duì)象,函數(shù)是對(duì)象,對(duì)象還是對(duì)象。
對(duì)象里面的一切都是屬性,只有屬性,沒(méi)有方法
那么這樣方法如何表示呢?——方法也是一種屬性。因?yàn)樗膶傩员硎緸殒I值對(duì)的形式。
而且,javascript中的對(duì)象可以任意的擴(kuò)展屬性,沒(méi)有class的約束。這個(gè)大家應(yīng)該都知道,就不再?gòu)?qiáng)調(diào)了。
先說(shuō)個(gè)最常見(jiàn)的例子:
var obj = { a: 10, b: function(x) { alert(this.a + x) }, c: { name: "yzh", age: 21 } }
以上代碼中,obj是一個(gè)自定義的對(duì)象,其中a、b、c就是它的屬性,而且在c的屬性值還是一個(gè)對(duì)象,它又有name、year兩個(gè)屬性。
這個(gè)可能比較好理解,那么函數(shù)和數(shù)組也可以這樣定義屬性嗎?——當(dāng)然不行,但是它可以用另一種形式,總之函數(shù)/數(shù)組之流,只要是對(duì)象,它就是屬性的集合。
var fn = function () { alert(100); }; fn.a = 10; fn.b = function () { alert(123); }; fn.c = { name: "yzh", age: 21 };
上段代碼中,函數(shù)就作為對(duì)象被賦值了a、b、c三個(gè)屬性——很明顯,這就是屬性的集合。
創(chuàng)建對(duì)象 前言(引用類型)都是對(duì)象,對(duì)象是屬性的集合。最需要了解的就是對(duì)象的概念。
這塊在《JS高級(jí)程序設(shè)計(jì)》也算是大章節(jié)下的一塊大內(nèi)容,我只把一些重要的概念寫出來(lái)讓大家理解,具體的深入要自己去看書(shū)中的講解。
函數(shù)和對(duì)象的關(guān)系對(duì)象都是通過(guò)函數(shù)創(chuàng)建的
function Fn() { this.name = "yzh"; this.year = 1996; } var fn1 = new Fn();
有人可能會(huì)舉出如下反例
var obj = { a: 10, b: 20 }; var arr = [5, "x", true];
這種做法屬于使用“快捷方式”,在編程語(yǔ)言中,一般叫做“語(yǔ)法糖”。
其實(shí)以上代碼的本質(zhì)是:
//var obj = { a: 10, b: 20 }; //var arr = [5, "x", true]; var obj = new Object(); obj.a = 10; obj.b = 20; var arr = new Array(); arr[0] = 5; arr[1] = "x"; arr[2] = true;
而其中的 Object 和 Array 都是函數(shù):
console.log(typeof (Object)); // function console.log(typeof (Array)); // function
prototype總結(jié):對(duì)象都是通過(guò)函數(shù)來(lái)創(chuàng)建的
函數(shù)也是一種對(duì)象。他也是屬性的集合,你也可以對(duì)函數(shù)進(jìn)行自定義屬性
每創(chuàng)建一個(gè)函數(shù),就會(huì)同時(shí)創(chuàng)建函數(shù)的prototype對(duì)象。
這個(gè)prototype的屬性值是一個(gè)對(duì)象(屬性的集合,再次強(qiáng)調(diào)!),默認(rèn)的只有一個(gè)叫做constructor的屬性,指向這個(gè)函數(shù)本身。
function Fn() { } Fn.prototype.name = "王福朋"; Fn.prototype.getYear = function () { return 1988; }; var fn = new Fn(); console.log(fn.name); console.log(fn.getYear());
Fn是一個(gè)函數(shù),fn對(duì)象是從Fn函數(shù)new出來(lái)的,這樣fn對(duì)象就可以調(diào)用Fn.prototype中的屬性。
因?yàn)槊總€(gè)對(duì)象都有一個(gè)隱藏的屬性——“__proto__”,這個(gè)屬性引用了創(chuàng)建這個(gè)對(duì)象的函數(shù)的prototype。
即:fn.__proto__ === Fn.prototype
這里的"__proto__"成為“隱式原型”
每個(gè)函數(shù)function都有一個(gè)prototype,即原型。這里再加一句話——每個(gè)對(duì)象都有一個(gè)__proto__,可成為隱式原型。__proto__用于指向創(chuàng)建它的構(gòu)造函數(shù)的原型對(duì)象
對(duì)象 person1 有一個(gè) __proto__屬性,創(chuàng)建它的構(gòu)造函數(shù)是 Person,構(gòu)造函數(shù)的原型對(duì)象是 Person.prototype ,所以:
person1.__proto__ == Person.prototype
又比如:obj這個(gè)對(duì)象本質(zhì)上是被Object函數(shù)創(chuàng)建的,因此obj.__proto__=== Object.prototype
在說(shuō)明“Object.prototype”之前,先說(shuō)一下自定義函數(shù)的prototype。自定義函數(shù)的prototype本質(zhì)上就是和 var obj = {} 是一樣的,都是被Object創(chuàng)建,所以它的__proto__指向的就是Object.prototype。
但是Object.prototype確是一個(gè)特例——它的__proto__指向的是null.
至于為什么簡(jiǎn)單解釋下:
所有的構(gòu)造器都來(lái)自于 Function.prototype,甚至包括根構(gòu)造器Object及Function自身。所有構(gòu)造器都繼承了·Function.prototype·的屬性及方法。如length、call、apply、bind
console.log(typeof Function.prototype) // function console.log(typeof Object.prototype) // object console.log(typeof Number.prototype) // object console.log(typeof Boolean.prototype) // object console.log(typeof String.prototype) // object console.log(typeof Array.prototype) // object console.log(typeof RegExp.prototype) // object console.log(typeof Error.prototype) // object console.log(typeof Date.prototype) // object console.log(typeof Object.prototype) // object
知道了所有構(gòu)造器(含內(nèi)置及自定義)的__proto__都是Function.prototype,
Function.prototype的__proto__是誰(shuí)呢?
console.log(Function.prototype.__proto__ === Object.prototype) // true
這說(shuō)明所有的構(gòu)造器也都是一個(gè)普通 JS 對(duì)象,可以給構(gòu)造器添加/刪除屬性等。同時(shí)它也繼承了Object.prototype上的所有方法:toString、valueOf、hasOwnProperty等。
最后Object.prototype的proto是誰(shuí)?
Object.prototype.__proto__ === null // true
已經(jīng)到頂了,為null。
訪問(wèn)一個(gè)對(duì)象的屬性時(shí),先在基本屬性中查找,如果沒(méi)有,再沿著__proto__這條鏈向上找
javascript中的繼承是通過(guò)原型鏈來(lái)體現(xiàn)的.
傳統(tǒng)原型語(yǔ)法
function Foo() {} Foo.prototype.a = 100; Foo.prototype.b = 200; var f1 = new Foo(); f1.a = 10; alert(f1.a); //10 alert(f1.b); //200
function Foo() {} var f1 = new Foo(); f1.a = 10; Foo.prototype.a = 100; Foo.prototype.b = 200; alert(f1.a); //10 alert(f1.b); //200
對(duì)象字面量方法添加屬性和方法的注意事項(xiàng)
function Foo() {} Foo.prototype = { a: 100, b: 200 } var f1 = new Foo(); f1.a = 10; alert(f1.a); //10 alert(f1.b); //200
function Foo() {} var f1 = new Foo(); f1.a = 10; Foo.prototype = { a: 100, b: 200 } alert(f1.a); //10 alert(f1.b); //undefined
原型的屬性和方法賦值要在,新建實(shí)例對(duì)象之前,不然無(wú)法獲得原型的值和屬性,alert返回相應(yīng)的undefined
重寫原型對(duì)象問(wèn)題接上面的例子講,如果在實(shí)例上添加新屬性,這個(gè)屬性就會(huì)屏蔽原型對(duì)象中保存的同名屬性,就是阻止訪問(wèn)了屬性,而不是修改原型的屬性。
function Foo() {} var f1 = new Foo(); f1.a = 10; Foo.prototype = { a: 100, b: 200 } alert(f1.a); //10 alert(f1.b); //undefined
End總結(jié):重寫原型對(duì)象切斷了現(xiàn)有原型與任何之前已經(jīng)存在的對(duì)象實(shí)例之間的關(guān)系,它們的引用的仍然是最初的原型。
暫時(shí)總結(jié)到此,有些知識(shí)點(diǎn)沒(méi)有講到,可能需要大家自己去看書(shū)或查閱資料來(lái)理解,本人理解也有限,文中若有難以理解的還望大神換個(gè)方式來(lái)闡述。
未完待續(xù)后續(xù)還有兩篇講解《執(zhí)行上下文與作用域》和《閉包》,最后一篇閉包可能會(huì)有一些前端面試題來(lái)講,并在文章末做個(gè)總結(jié)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/83048.html
摘要:不理解沒(méi)關(guān)系,下面會(huì)結(jié)合圖例分析上一篇高級(jí)程序設(shè)計(jì)筆記創(chuàng)建對(duì)象下一篇高級(jí)程序設(shè)計(jì)筆記繼承參考之原型鏈的解讀三張圖搞懂的原型對(duì)象與原型鏈繼承與原型鏈 文章直接從原型圖解開(kāi)始的,如果對(duì)一些概念不太清除,可以結(jié)合后面幾節(jié)查看 1. 圖解原型鏈 1.1 鐵三角關(guān)系(重點(diǎn)) function Person() {}; var p = new Person(); showImg(https://s...
摘要:繼承和前面兩篇文章中的知識(shí)非常相關(guān),如果對(duì)函數(shù)創(chuàng)建原理和原型鏈不熟悉,請(qǐng)猛戳高級(jí)程序設(shè)計(jì)筆記創(chuàng)建對(duì)象高級(jí)程序設(shè)計(jì)筆記原型圖解繼承,通俗的說(shuō),就是將自身不存在的屬性或方法,通過(guò)某種方式為自己所用文章分別介紹原型鏈繼承繼承借用構(gòu)造函數(shù)繼承組合繼 繼承和前面兩篇文章中的知識(shí)非常相關(guān),如果對(duì)函數(shù)創(chuàng)建原理和原型鏈不熟悉,請(qǐng)猛戳:《javascript高級(jí)程序設(shè)計(jì)》筆記:創(chuàng)建對(duì)象《javascri...
原型鏈之前一直都不是很理解,這兩天把《你不知道的JavaScript》和《JavaScript高級(jí)程序設(shè)計(jì)》的原型鏈那章看完后有所理解,在這里先記下來(lái),加深印象。 什么是原型對(duì)象 要講清楚什么是原型鏈需要從原型對(duì)象開(kāi)始談,那么什么是原型對(duì)象呢?《JavaScript高級(jí)程序設(shè)計(jì)》中是這樣講的: 無(wú)論什么時(shí)候,只要?jiǎng)?chuàng)建了一個(gè)新函數(shù),就會(huì)根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個(gè)prototype屬性,這個(gè)屬...
摘要:探索是如何判斷的表達(dá)式如果函數(shù)的顯式原型對(duì)象在對(duì)象的隱式原型鏈上,返回,否則返回是通過(guò)自己產(chǎn)生的實(shí)例案例案例重要注意的顯示原型和隱式原型是一樣的。面試題測(cè)試題測(cè)試題報(bào)錯(cuò)對(duì)照下圖理解 原型與原型鏈深入理解(圖解) 原型(prototype) 函數(shù)的 prototype 屬性(圖) 每個(gè)函數(shù)都有一個(gè)prototype屬性,它默認(rèn)指向一個(gè)Object空對(duì)象(即稱為:原型對(duì)象) 原型對(duì)象中有...
摘要:此時(shí)的原型對(duì)象包括一個(gè)指向另一個(gè)原型的指針,相應(yīng)的,另一個(gè)原型中的指向另一個(gè)構(gòu)造函數(shù)。這種關(guān)系層層遞進(jìn),就通過(guò)一個(gè)原型對(duì)象鏈接另一個(gè)構(gòu)造函數(shù)的原型對(duì)象的方式實(shí)現(xiàn)了繼承。 讀這篇之前,最好是已讀過(guò)我前面的關(guān)于對(duì)象的理解和封裝類的筆記。第6章我一共寫了3篇總結(jié),下面是相關(guān)鏈接:讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之理解對(duì)象讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之封裝類 一...
摘要:繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了屬性,但沒(méi)有繼承原型中的方法。上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。 ECMAScript只支持實(shí)現(xiàn)繼承,主要依靠原型鏈來(lái)實(shí)現(xiàn)。與實(shí)現(xiàn)繼承對(duì)應(yīng)的是接口繼承,由于script中函數(shù)沒(méi)有簽名,所以無(wú)法實(shí)現(xiàn)接口繼承。 一、原型鏈 基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用...
閱讀 926·2021-11-19 11:29
閱讀 3407·2021-09-26 10:15
閱讀 3130·2021-09-22 10:02
閱讀 2502·2021-09-02 15:15
閱讀 2022·2019-08-30 15:56
閱讀 2488·2019-08-30 15:54
閱讀 3034·2019-08-29 16:59
閱讀 704·2019-08-29 16:20