成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

【呆萌の研究】JavaScript常見(jiàn)的繼承方式

馬永翠 / 993人閱讀

摘要:構(gòu)造函數(shù)構(gòu)造操作符調(diào)用的函數(shù)就是構(gòu)造函數(shù)。其和其構(gòu)造函數(shù)的指向相同。而構(gòu)造函數(shù)屬性指向的對(duì)象帶有屬性,指向函數(shù)自身。,回歸構(gòu)造函數(shù)繼承,仔細(xì)看看誕生的嘻嘻和哈哈兩位同學(xué)可以看到兩個(gè)實(shí)例都擁有了和兩個(gè)屬性,因?yàn)榉椒ǖ倪\(yùn)行類(lèi)似于執(zhí)行了和。

最近在看《JavaScript設(shè)計(jì)模式》,然后開(kāi)篇復(fù)習(xí)了JavaScript中的幾種繼承方式,自己似乎也沒(méi)有怎么仔細(xì)探究過(guò),目前自己沒(méi)怎么碰到過(guò)應(yīng)用的場(chǎng)景(噗),所以借這次機(jī)會(huì)好好來(lái)屢屢思路。

方式1 類(lèi)式繼承

例子

function Person() {
    this.telephone = ["000-0000-0000"];
}

function Student(className) {
    this.className = className;
}

Student.prototype = new Person();
var Haha = new Student(1);
var Xixi = new Student(2);

創(chuàng)建好父類(lèi)和子類(lèi)。聯(lián)系他們的方式是把學(xué)生的prototype指向一個(gè)人的實(shí)例。

問(wèn):prototype是什么?
幾乎任何對(duì)象有一個(gè)[[prototype]]屬性,在標(biāo)準(zhǔn)中,[[prototype]]一個(gè)隱藏屬性,指向的是這個(gè)對(duì)象的原型。而它的指向是由構(gòu)造該對(duì)象的方法決定的:
1.對(duì)象字面量構(gòu)造:其[[prototype]]指向Object.prototype。

var person = {};

2.構(gòu)造函數(shù)構(gòu)造:new操作符調(diào)用的函數(shù)就是構(gòu)造函數(shù)。其[[prototype]]和其構(gòu)造函數(shù)的prototype指向相同。而構(gòu)造函數(shù)prototype屬性指向的對(duì)象帶有constructor屬性,指向函數(shù)自身。

function Person(){}
var person = new Person();

此圖為Person的prototype內(nèi)容,可以看到constructor屬性實(shí)際指向的就是Person()函數(shù)。(小綠色框框內(nèi)和外面綠色框框其實(shí)是同一個(gè)內(nèi)容)。

3.Object.create構(gòu)造的。

var person = {};
var Haha = Object.create(person);

這里對(duì)象Haha的[[prototype]]指向?qū)ο髉erson。也可以寫(xiě)null,此時(shí)對(duì)象Haha就沒(méi)有原型。

首先要分清楚類(lèi)和實(shí)例,在控制臺(tái)顯示中,只有類(lèi)才會(huì)有prototype屬性,而實(shí)例是擁有一個(gè)名為_(kāi)proto_的屬性,它會(huì)指向構(gòu)造它函數(shù)的原型,兩者本質(zhì)都是一個(gè)指針。

function Person() {
   this.telephone = ["000-0000-0000"];
}
var Hehe = new Person(); 
console.log(Person.prototype);
console.log(Hehe);

以上代碼運(yùn)行結(jié)果:

可以瞧見(jiàn),這里Hehe的_proto_是指向了Person.prototype

問(wèn):new關(guān)鍵字的作用是什么?
new關(guān)鍵字運(yùn)作的過(guò)程如下,引用自《JavaScript》高級(jí)程序設(shè)計(jì):

1、創(chuàng)建一個(gè)空對(duì)象,并且 this 變量引用該對(duì)象,同時(shí)還繼承了該函數(shù)的原型。  2、屬性和方法被加入到 this 引用的對(duì)象中。 
3、新創(chuàng)建的對(duì)象由 this 所引用,并且最后隱式的返回 this。

簡(jiǎn)單來(lái)說(shuō),它創(chuàng)建了一個(gè)空對(duì)象,指定了原型,把屬性方法進(jìn)行拷貝,并把this指向進(jìn)行了改變。假如我們把上面的代碼改成:

function Person() {
 this.telephone = ["000-0000-0000"];
}
        
var Hehe = Person();
console.log(Hehe.telephone);

去掉new關(guān)鍵詞賦予Person(),會(huì)報(bào)錯(cuò),而輸出window.telphone得到的就是["000-0000-0000"]。因?yàn)楹瘮?shù)的返回值(沒(méi)有返回值所以是undefined)賦予給了Hehe,嘗試去讀取undefined的屬性,報(bào)錯(cuò)了。而此時(shí)函數(shù)運(yùn)行中的this是全局變量window。

So,回歸類(lèi)式繼承,仔細(xì)看看誕生的嘻嘻和哈哈兩位同學(xué)

會(huì)發(fā)現(xiàn),各自都有自己的班級(jí)名屬性,但是原型指向的是同一個(gè)Person實(shí)例,所以如果嘻嘻有兩個(gè)號(hào)碼,或者他要更改自己的號(hào)碼,那哈哈的電話(huà)號(hào)碼也會(huì)發(fā)生變化,他們只能共享這個(gè)電話(huà)號(hào)碼。

方式2 構(gòu)造函數(shù)繼承

例子

function Person(name) {
    this.name = name;
}

Person.prototype.showName = function() {
    console.log(this.name);
}

function Student(name, className) {
    this.className = className;
    Person.call(this, name);
}
var Haha = new Student("Haha", 1);
var Xixi = new Student("Xixi", 2);

問(wèn):call函數(shù)的運(yùn)作過(guò)程?
call函數(shù)和apply函數(shù)的作用相同,不同之處就是apply函數(shù)只能傳入2個(gè)參數(shù),而call函數(shù)可以有多個(gè)。F.call(thisArg,[arg1……]) 函數(shù)的運(yùn)作過(guò)程如下(來(lái)源網(wǎng)絡(luò)):

1.先判斷F是否為一個(gè)函數(shù),如果不是一個(gè)函數(shù),那么將拋出TypeError異常。 
2.創(chuàng)建一個(gè)內(nèi)部類(lèi)型空列表list
3.然后如果參數(shù)除去thisArg外還有其他參數(shù)的話(huà),就將這些值添加到list中
4.thisArg和list作為F內(nèi)部屬性[[Call]]的參數(shù)傳入調(diào)用進(jìn)行函數(shù)的執(zhí)行操作

簡(jiǎn)而言之就是它把一個(gè)函數(shù)的對(duì)象上下文改成了由 thisArg指定的新對(duì)象。

So,回歸構(gòu)造函數(shù)繼承,仔細(xì)看看誕生的嘻嘻和哈哈兩位同學(xué)

可以看到兩個(gè)實(shí)例都擁有了className和name兩個(gè)屬性,因?yàn)閏all方法的運(yùn)行類(lèi)似于執(zhí)行了Haha.name="Haha"Xixi.name="Xixi"。
但是因?yàn)闆](méi)有與父類(lèi)的原型相聯(lián)系,所以父類(lèi)原型中的方法,不能得到繼承。運(yùn)行Haha.showName()會(huì)得到報(bào)錯(cuò)。

方式3 組合繼承

例子

function Person(name) {
    this.name = name;
}

Person.prototype.showName = function() {
    console.log(this.name);
}

function Student(name, className) {
    this.className = className;
    Person.call(this, name);
}
Student.prototype = new Person();
Student.prototype.showClassName = function() {
     console.log(this.className);
}

var Haha = new Student("Haha", 1);
var Xixi = new Student("Xixi", 2);

組合繼承綜合了類(lèi)式繼承和構(gòu)造函數(shù)繼承,在把父類(lèi)的屬性繼承后,把子類(lèi)的原型指向了父類(lèi)實(shí)例,這樣就可以繼承父類(lèi)原型的方法了。
但是這里相當(dāng)于使用了兩次父類(lèi)函數(shù),并且子類(lèi)不是父類(lèi)的實(shí)例,子類(lèi)的原型是父類(lèi)的實(shí)例,所以還會(huì)有更好的方法。

方式4 原型繼承
function inheritObject(o) {
 function F() {}
 F.prototype = o;
 return new F();
}

var person = {
 name: "unknown",
 telephone: ["000-0000-0000"]
}

var Xixi = inheritObject(person);
Xixi.name = "Xixi";
Xixi.telephone.push("111-1111-1111");

var Haha = inheritObject(person);
Haha.name = "Haha";

仔細(xì)看看誕生的嘻嘻和哈哈兩位同學(xué)

這里.name給Xixi實(shí)例添加了一個(gè)自己的name屬性,而push操作是直接影響原型中引用變量,所以改進(jìn)之后又有了下面這種方式。
在這里我產(chǎn)生了一個(gè)疑問(wèn),為什么name屬性是自己添加新的,而telephone是采用原來(lái)的。于是添加了一個(gè)age屬性,執(zhí)行Xixi.age++操作。

這里可以看到實(shí)例重新添加了一個(gè)age屬性,所以我們可以說(shuō)只要是改變?cè)蛯傩缘闹?,就?huì)把新的屬性加在實(shí)例上,引用不改變是因?yàn)橐玫牡刂愤€沒(méi)有改變。

方式5 寄生式繼承

寄生式繼承是在原型繼承的基礎(chǔ)之上,我們需要再添加一下代碼:

function createPerson(obj) {
 var o = inheritObject(obj);
 o.getName = function(){
  console.log(name);
 }
 return o;
}

這樣就給得到的對(duì)象添加了公共方法。

方式6 寄生組合式繼承

寄生組合式繼承是為了彌補(bǔ)組合式繼承的缺點(diǎn),是在寄生式繼承+構(gòu)造函數(shù)繼承組合而成的:

function inheritObject(o) {
 function F() {}
 F.prototype = o;
 return new F();
}
function inheritPrototype(subClass, superClass) {
 //復(fù)制一份父類(lèi)原型
 var p = inheritObject(superClass.prototype);
 //修正重寫(xiě)子類(lèi)原型導(dǎo)致constructor屬性被修改
 p.constructor = subClass;
 //設(shè)置子類(lèi)原型
 subClass.prototype = p;
}

function Person(name) {
    this.name = name;
}

Person.prototype.showName = function() {
    console.log(this.name);
}

function Student(name, className) {
    this.className = className;
    Person.call(this, name);
}

inheritPrototype(Student, Person);

Student.prototype.showClassName = function() {
     console.log(this.className);
}

var Xixi = new Student("Xixi",2);
var Haha = new Student("Haha",1);

以下為嘻嘻和哈哈的內(nèi)容:

可以對(duì)比一下組合式繼承的結(jié)果:

不同的地方在于把子類(lèi)原型的構(gòu)造函數(shù)改成了實(shí)例對(duì)應(yīng)的構(gòu)造函數(shù),在組合繼承中子類(lèi)原型直屬并沒(méi)有constructor屬性。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/93124.html

相關(guān)文章

  • 萌の研究JavaScriptの閉包

    摘要:為什么會(huì)產(chǎn)生閉包究其根本,是因?yàn)榇淼暮瘮?shù)包含的作用域。而在作用域鏈中,外部函數(shù)的活動(dòng)對(duì)象始終處于第二位,外部函數(shù)的外部函數(shù)的活動(dòng)對(duì)象處于第三位直到作為作用域鏈終點(diǎn)的全局執(zhí)行環(huán)境。 前言 此文的內(nèi)容主要是來(lái)自看書(shū)的總結(jié)+小小的實(shí)踐哦~會(huì)不斷更新總結(jié)。 什么是閉包 書(shū)上是這樣定義閉包的: 有權(quán)訪(fǎng)問(wèn)另一個(gè)函數(shù)作用域中變量的函數(shù)。 舉一個(gè)例子: function test(){ va...

    CHENGKANG 評(píng)論0 收藏0
  • 萌の研究】圣杯布局引發(fā)對(duì)margin負(fù)值研究

    摘要:?jiǎn)栴}起源以前一直就聽(tīng)說(shuō)圣杯布局,但是沒(méi)有怎么去用過(guò),然后這次偶然接觸到了,就學(xué)習(xí)了一下。繼續(xù)試驗(yàn)我們可以嘗試改變的值,去看看位置的變化。為了方便我們計(jì)算,另外寫(xiě)了一個(gè)類(lèi)似的布局,內(nèi)容區(qū)的寬度是,三個(gè)的寬度也都是。 問(wèn)題の起源 以前一直就聽(tīng)說(shuō)圣杯布局,但是沒(méi)有怎么去用過(guò),然后這次偶然接觸到了,就學(xué)習(xí)了一下。這是一個(gè)我從別人寫(xiě)的文章中復(fù)制過(guò)來(lái)的,關(guān)于圣杯布局的比較簡(jiǎn)單的說(shuō)明 通過(guò)縮放頁(yè)面就...

    zhangke3016 評(píng)論0 收藏0
  • 萌の體驗(yàn)】vue.js初次體驗(yàn)

    摘要:官方默認(rèn)項(xiàng)目是存放了一個(gè)為的打開(kāi)文件夾有一個(gè),還有一個(gè)名為組件的文件夾,里面放了一個(gè)文件。部分我們會(huì)發(fā)現(xiàn)這幾排字就是顯示在頁(yè)面的幾排文字部分這其中的這個(gè)文件引入了,還有上述的。結(jié)合查詢(xún)其他說(shuō)法,就是說(shuō)它會(huì)把是的元素以形式替換。 前言 我很早就想來(lái)學(xué)習(xí)學(xué)習(xí)vue.js啦,終于有了那么一些空閑的時(shí)間可以拿來(lái)學(xué)習(xí),于是從前天開(kāi)始我就每天抽一個(gè)多小時(shí)來(lái)體驗(yàn)vue.js。當(dāng)然啦,因?yàn)槭切“兹腴T(mén),...

    wdzgege 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<