国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

我來重新學(xué)習(xí)js 的面向?qū)ο螅╬art 5)

BicycleWarrior / 730人閱讀

摘要:無限增殖返回蘋果返回香蕉返回返回使用的新語法方法會創(chuàng)建一個新對象,使用現(xiàn)有的對象來提供新創(chuàng)建的對象的。是新增的,用來規(guī)范原型式繼承。這里將返回的新對象放到子類的原型對象里面,這樣子類就擁有了父類的原型對象,也就實現(xiàn)了方法的繼承。

這是最后的最后了,我會順便總結(jié)一下各種繼承方式的學(xué)習(xí)和理解。(老板要求什么的,管他呢)

一、繼承-組合繼承、偽經(jīng)典繼承


圖片來自:http://www.joyme.com/xinwen/2...

這是一種將原型鏈和借用構(gòu)造函數(shù)的技術(shù)結(jié)合起來的一種繼承模式。不是假合體,是真合體!

核心思想是:

使用原型鏈實現(xiàn)對原型屬性和方法的繼承。

通過借用改造函數(shù)來實現(xiàn)對實例屬性的繼承。

很像之前說過的組合使用構(gòu)造函數(shù)模式和原型模式
// 父類構(gòu)造函數(shù)
function Food(name) {
  this.name = name;
  this.colors = ["red", "blue"];
}
// 父類原型對象的方法
Food.prototype.sayName = function() {
  console.log("我是" + this.name);
};
// 子類構(gòu)造函數(shù)
function Fruit(name, place) {
  // 在構(gòu)造函數(shù)里面調(diào)用父類搞糟函數(shù),實現(xiàn)屬性繼承
  Food.call(this, name);
  this.place = place;
}
// 將父類的實例賦值給子類的原型對象,實現(xiàn)方法繼承
Fruit.prototype = new Food();
// 添加子類原型對象的方法
Fruit.prototype.sayPlace = function() {
  console.log(this.place);
};

var food1 = new Fruit("蘋果", "非洲");
food1.colors.push("black");
console.log(food1.colors); // 返回 [ "red", "blue", " black" ]
food1.sayName(); // 返回 我是蘋果
food1.sayPlace(); // 返回 非洲

var food2 = new Fruit("香蕉", "亞洲");
food2.colors.push("yellow");
console.log(food2.colors); // 返回 [ "red", "blue", "yellow" ]
food2.sayName(); // 返回 我是香蕉
food2.sayPlace(); // 返回 亞洲

可以看到超類構(gòu)造函數(shù) Food里的屬性(namecolors)和超類構(gòu)造函數(shù)的原型對象的方法( sayName )都能夠被繼承,并且對于引用類型的值也不會出現(xiàn)相互影響的情況,而子類構(gòu)造函數(shù)的屬性(place)和子類構(gòu)造函數(shù)的原型對象的方法( sayPlace)也能夠很好的使用,不會被覆蓋,他們相互共享又相互獨立。

這里的屬性繼承是通過 call 方式,將父類的屬性放到子類的構(gòu)造函數(shù)里面,也就是借用構(gòu)造函數(shù)模式。

這里的方法繼承是通過將父類的實例放到子類的原型對象上,也就是原型鏈模式。

也存在一些問題

它需要調(diào)用兩次超類型構(gòu)造函數(shù),一次是在創(chuàng)建子類型原型的時候,另一次是在子類型構(gòu)造函數(shù)內(nèi)部,

也需要重寫 constructor 屬性,因為原型對象被重寫了,constructor就丟失了

// 。。。。。。。。
// 子類構(gòu)造函數(shù)
function Fruit(name, place) {
  // 在構(gòu)造函數(shù)里面調(diào)用父類搞糟函數(shù),實現(xiàn)屬性繼承
  Food.call(this, name); // 第二次調(diào)用父類構(gòu)造函數(shù)
  this.place = place;
}
// 將父類的實例賦值給子類的原型對象,實現(xiàn)方法繼承
Fruit.prototype = new Food(); // 第一次調(diào)用父類構(gòu)造函數(shù)
Fruit.prototype.constrcutor=Fruit;//因重寫原型而失去constructor屬性,所以要對constrcutor重新賦值
// 添加子類原型對象的方法
Fruit.prototype.sayPlace = function() {
  console.log(this.place);
};
// 。。。。。。。
在一般情況下,這是我們在 javascript 程序開發(fā)設(shè)計中比較常用的繼承模式了。

基于以上原因,我們需要引入寄生組合式繼承來解決它的存在的問題,實現(xiàn)完美的繼承。但是在了解它之前,需要先了解寄生式繼承,而了解寄生式繼承之前,需要了解原型式繼承,他們是一個接一個的推導(dǎo)出來的。

二、繼承-原型式繼承


圖片來自:http://acg.shunwang.com/2014/...

核心思想是借助原型可以基于已有的對象創(chuàng)建新對象,同時不必因此創(chuàng)建自定義類型。

以一個對象實例來做模板進(jìn)行復(fù)制,并且是借助原型鏈模式進(jìn)行特殊復(fù)制

這種復(fù)制的方式會有一些特別的地方,例如,引用類型的值問題也是無法解決,復(fù)制可以借助 es5語法也可以不借助,前者更加強大一些。

// 原型式繼承的關(guān)鍵-復(fù)制
function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

var food1 = {
  name: "蘋果",
  colors: ["red", "blue"]
};
// 繼承
var food2 = object(food1);

food2.name = "香蕉";
food2.colors.push("black");

//。。。。。。無限增殖

console.log(food1.name); // 返回 蘋果
console.log(food2.name); // 返回 香蕉
console.log(food1.colors); // 返回 [ "red", "blue", "black" ]
console.log(food2.colors); // 返回 [ "red", "blue", "black" ]
2.1 使用 es5的新語法:Object.create()

Object.create()方法會創(chuàng)建一個新對象,使用現(xiàn)有的對象來提供新創(chuàng)建的對象的__proto__

Object.create()是es5新增的,用來規(guī)范原型式繼承。

如果單純使用的話,效果跟之前的差別不大,參考下面例子:

var food1 = {
  name: "蘋果",
  colors: ["red", "blue"]
};

var food2 = Object.create(food1);
food2.name = "香蕉";
food2.colors.push("black");

console.log(food1.name); // 返回 蘋果
console.log(food2.name); // 返回 香蕉
console.log(food1.colors); // 返回 [ "red", "blue", "black" ]
console.log(food2.colors); // 返回 [ "red", "blue", "black" ]

如果注意使用它的第二個參數(shù)的話,差別就不一樣了:

var food1 = {
  name: "蘋果",
  colors: ["red", "blue"]
};

var food2 = Object.create(food1, {
  name: { value: "香蕉" },
  colors: { // !!!!!
    value: ["red", "blue", "black"]
  }
});

console.log(food1.name); // 返回 蘋果
console.log(food2.name); // 返回 香江
console.log(food1.colors); // 返回 [ "red", "blue" ]  !!!!!
console.log(food2.colors); // 返回 [ "red", "blue", "black" ]

可以看到引用類型的數(shù)值不會被共享,實現(xiàn)了很好的繼承效果。

出現(xiàn)這個情況主要是因為如果使用 push 的話,還是操作同一個內(nèi)存指針,使用Object.create的話,會重新添加到新創(chuàng)建對象的可枚舉屬性,不是同一個內(nèi)存指針了。
2.2 發(fā)現(xiàn)一些有價值的東西


圖片來自:http://www.cifnews.com/articl...

參考 mdn 里面的介紹,會發(fā)現(xiàn)一些更有價值的東西,可以用 Object.create實現(xiàn)類式繼承:

// Shape - 父類(superclass)
function Shape() {
  this.x = 0;
  this.y = 0;
}

// 父類的方法
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info("Shape moved.");
};

// Rectangle - 子類(subclass)
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// 子類續(xù)承父類
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log(rect instanceof Rectangle); // true
console.log(rect instanceof Shape); // true
rect.move(1, 1); // Outputs, "Shape moved."

Object.create會將參數(shù)里的對象添加到它返回的新對象的原型對象里面去,這樣首先生成了一個新對象,并且該對象的原型對象是參數(shù)里的值,即Shape.prototype,新對象是臨時的,暫時看不到,這個臨時的新對象里面就包含了父類原型對象。

這里將Object.create返回的新對象放到子類的原型對象里面,這樣子類就擁有了父類的原型對象,也就實現(xiàn)了方法的繼承。

手動設(shè)置一個子類的原型對象的 constructor,是為了重新指定子類的構(gòu)造函數(shù)名字,這樣子類實例對象就可以查看到他的構(gòu)造函數(shù)是誰,證明是某個實例來自于哪一個構(gòu)造函數(shù),這樣代碼和結(jié)構(gòu)都會清晰。

屬性的繼承還是有 call 實現(xiàn)。

還有更屌炸飛的東西,如果你希望能繼承到多個對象,則可以使用混入的方式。

function MyClass() {
     SuperClass.call(this);
     OtherSuperClass.call(this);
}

// 繼承一個類
MyClass.prototype = Object.create(SuperClass.prototype);
// 混合其它
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// 重新指定constructor
MyClass.prototype.constructor = MyClass;

MyClass.prototype.myMethod = function() {
     // do a thing
};

Object.assign 會把 OtherSuperClass原型上的函數(shù)拷貝到 MyClass原型上,使 MyClass 的所有實例都可用 OtherSuperClass 的方法。

Object.assign 是在 ES2015 引入的,且可用 polyfilled。要支持舊瀏覽器的話,可用使用 jQuery.extend() 或者 _.assign()

與時俱進(jìn),紅寶書《javascript 高級程序設(shè)計第三版》 也并不是無敵的,當(dāng)然,一下子知識量太大,我們吸收不了,所以這里不展開細(xì)說。
三、繼承-寄生式繼承

在引入寄生組合式繼承之前,需要了解什么是寄生式繼承。


圖片來自:https://2ch.hk/b/arch/2017-01...

寄生式繼承的思路跟寄生構(gòu)造函數(shù)模式和工廠模式很類似,核心思想是創(chuàng)建一個僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式來增強對象,最后再像真得是它做了所有工作一樣返回對象。

感覺像是原型式繼承的升級版!
// 原型式繼承的關(guān)鍵-復(fù)制
function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

function createFood(original) {
  var clone = object(original);
  clone.sayName = function(name) {
    console.log(name);
  };
  return clone;
}

var food1 = {
  name: "蘋果"
};
var food2 = createFood(food1);
console.log(food2.name); // 返回蘋果
food2.sayName("香蕉"); // 返回香蕉

可以看到 name 屬性是沒有變化的,可以將一些共享的屬性放在里面來形成復(fù)制。

這里需要注意如果需要給添加的新函數(shù)傳參的話,是不可以在”克隆“的時候傳的,需要在外面使用的時候傳。

這是一種比較簡單的實現(xiàn)繼承的方式,在不考慮自定義類型和構(gòu)造函數(shù)的情況下,也算是一種有用的模式。
四、繼承-寄生組合式繼承
終于到了主角了。


圖片來自:https://www.9yread.com/book/1...

寄生組合式繼承的核心思想是:

通過借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈的混成形式來繼承方法。

其背后的思路是不必為了指定子類型的原型而調(diào)用超類型的構(gòu)造函數(shù)。

使用寄生式繼承來繼承超類型的原型,然后再將結(jié)果指定給子類型的原型。

好復(fù)雜的解釋,先看看代碼吧:

// object 函數(shù)可以用 Object.create 來代替。
function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

// 這里是關(guān)鍵
function inheritPrototype(subType, superType) {
  // ①將超類原型放到一個臨時的對象里面(創(chuàng)建超類型圓形的副本)
  var prototype = object(superType.prototype);
  // ②重新指定這個臨時對象的constructor 為 子類構(gòu)造函數(shù)
  prototype.constructor = subType;
  // ③將這個臨時對象賦值給子類的原型對象
  subType.prototype = prototype;
}

function Food(name) {
  this.name = name;
  this.colors = ["red", "blue"];
}

Food.prototype.sayName = function() {
  console.log(this.name);
};

function Fruit(name, place) {
  Food.call(this, name);
  this.place = place;
}

inheritPrototype(Fruit, Food);
Fruit.prototype.sayPlace = function() {
  console.log(this.place);
};

var food1 = new Fruit("蘋果", "非洲");
var food2 = new Fruit("香蕉", "亞洲");
console.log(food1.sayName()); // 返回 蘋果
console.log(food1.sayPlace()); // 返回 非洲

food1.colors.push("black");
console.log(food1.colors); // 返回 [ "red", "blue", "black" ]
console.log(food2.colors); // 返回 [ "red", "blue" ]

console.log(food1 instanceof Fruit); // 返回 true
console.log(food1 instanceof Food); // 返回 true
console.log(Fruit.prototype.isPrototypeOf(food1)); // 返回 true
console.log(Food.prototype.isPrototypeOf(food1)); // 返回 true
object 函數(shù)可以用 Object.create來代替。

借助這個圖理解一下,這種繼承模式拆開來看就是寄生式(復(fù)制)+組合式(原型鏈+構(gòu)造函數(shù))


圖片來自https://www.jianshu.com/p/004...

原型鏈沒被切斷,是因為是用了寄生(復(fù)制)的方式來進(jìn)行超類原型對象的復(fù)制,整個復(fù)制的話,會保存它的原型鏈,然后將這個復(fù)制出來的原型對象直接賦值給子類,所以原型鏈?zhǔn)峭暾摹?/p>

沒有出現(xiàn)之前組合繼承的兩次調(diào)用問題,是因為它有一個中間臨時過渡的對象,省去了一次調(diào)用構(gòu)造父類函數(shù)的機(jī)會。

沒有出現(xiàn)引用類型的值共享問題,是因為在寄生(復(fù)制)之后才可以用原型鏈+構(gòu)造函數(shù)的,這樣就很好的隔離了超類和子類的引用類型的值的問題了。

總結(jié)

幾乎涵蓋了所有 javascript 的繼承模式了:

圖片來自:https://zhuanlan.zhihu.com/p/...

有幾點是我覺得可以總結(jié)一下,前人栽樹,后人乘涼:

書不要讀死,如果單純讀《javascript 高級程序設(shè)計第三版》是不可能完整了解 javascript 的,起碼在面向?qū)ο筮@部分是不行的,很多網(wǎng)上的大(zhuang)牛(bi)都會叫你認(rèn)真閱讀這本書,但是對于初學(xué)者來說,基本是很難理解得到作者的思路和意思的,不是資質(zhì)問題,是閱歷和經(jīng)驗和知識含量不足的限制。

看不懂,不要緊,多看,多查閱資料,記得用 google 查,baidu 只會讓你多了解一些廣告罷了。

網(wǎng)上的文章質(zhì)量也是參差不齊的,就算是我這篇裝逼文,也是我自己覺得很好,但是未必能夠面面俱到,但是人生本來就難以面面俱到,不是嗎?重要的是,我用我的經(jīng)驗寫了,你能看明白一些是一些,看不明白就當(dāng)飯后爾爾罷了,不用糾結(jié)。

要自己做實驗,自己輸出一些結(jié)果,對比理論,對比別人的結(jié)果和分析,這樣才能理解得好一些。

學(xué)習(xí)第一次發(fā)現(xiàn)完全懵逼的話,就嘗試去組織一個脈絡(luò)結(jié)構(gòu),就好像我這樣,嘗試做一個故事代入,一環(huán)扣一環(huán)來理解,雖然《javascript 高級程序設(shè)計第三版》這本書里面也有,但是感覺后面開始省略很多一部分了,以致迷失了。

不要怕,多學(xué)習(xí),莫道前路無知己,天下誰人不識君,加油加油,也是自勉。

參考內(nèi)容

紅寶書,javascript 高級程序設(shè)計第三版

原文轉(zhuǎn)載:
https://www.godblessyuan.com/...

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/98341.html

相關(guān)文章

  • 我來重新學(xué)習(xí) javascript 面向對象part 1)

    摘要:其實在之前的工廠模式里面,也存在這個問題,不過工廠模式更徹底,直接完全創(chuàng)建一個新對象,而構(gòu)造函數(shù)模式的話只是方法會被重新創(chuàng)建。 我來重新學(xué)習(xí) javascript 的面向?qū)ο螅╬art 1) 很多job 的描述都說要求精通 javascript 面向?qū)ο缶幊蹋歉鶕?jù)一般的套路,寫精通其實就是熟練,寫熟練其實就是一般,寫一般其實就是懵逼! showImg(https://segment...

    myshell 評論0 收藏0
  • 我來重新學(xué)習(xí)js面向對象part 4)

    摘要:我是的可以改變函數(shù)的對象的指向拋出異常,沒有這個因為子類和超類都是構(gòu)造函數(shù),那么就會有之前說的,構(gòu)造函數(shù)在的時候,里面的方法函數(shù)會重復(fù)創(chuàng)建實例,導(dǎo)致資源浪費。 我來重新學(xué)習(xí)js 的面向?qū)ο螅╬art 4) 續(xù)上一篇,隨著業(yè)務(wù)越來越大,要考慮一些繼承的玩意了,大千世界,各種東西我們要認(rèn)識和甄別是需要靠大智慧去分門別類,生物學(xué)中把動植物按界、門、綱、目、科、屬、種進(jìn)行分類的方法可能是最有代...

    MAX_zuo 評論0 收藏0
  • 我來重新學(xué)習(xí) javascript 面向對象part 3)

    摘要:二動態(tài)原型模式動態(tài)原型模式的特點是,在構(gòu)造函數(shù)里面增加判斷處理是否添加原型對象屬性。他依然有一個嚴(yán)重的問題,就是原型對象和實例和構(gòu)造函數(shù)之間沒辦法關(guān)聯(lián),這樣不適合在有一定規(guī)模復(fù)雜度的程序開發(fā)中使用。 續(xù)上一集內(nèi)容,有一些數(shù)據(jù)不需要共享的時候,但是又想實現(xiàn)共享數(shù)據(jù)處理,魚與熊掌,都要兼得(老板就是這么霸氣),那么經(jīng)過工程師們的智慧交流,他們發(fā)現(xiàn)現(xiàn)實并非那么殘酷,還有一些辦法可取的,也就是...

    Elle 評論0 收藏0
  • 我來重新學(xué)習(xí) javascript 面向對象part 2)

    摘要:先來說其實構(gòu)造函數(shù)也有,原型對象有,實例有也有,或者更加籠統(tǒng)的說,所有對象都是有的。構(gòu)造函數(shù)的原型對象上的會指向構(gòu)造函數(shù)。由于屬性是可以變更的,所以未必真的指向?qū)ο蟮臉?gòu)造函數(shù),只是一個提示。 續(xù)上一集內(nèi)容,通過構(gòu)造函數(shù)的方式,成功地更新了生產(chǎn)技術(shù),老板笑呵呵,工人少奔波,只是問題總比辦法多,又遇到一個新問題,就是會造成一些資源的重復(fù)和浪費,那么經(jīng)過工程師們的智慧交流,他們產(chǎn)生了一個新技...

    silvertheo 評論0 收藏0
  • 【全文】狼叔:如何正確學(xué)習(xí)Node.js

    摘要:感謝大神的免費的計算機(jī)編程類中文書籍收錄并推薦地址,以后在倉庫里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡介現(xiàn)在,越來越多的科技公司和開發(fā)者開始使用開發(fā)各種應(yīng)用。 說明 2017-12-14 我發(fā)了一篇文章《沒用過Node.js,就別瞎逼逼》是因為有人在知乎上黑Node.js。那篇文章的反響還是相當(dāng)不錯的,甚至連著名的hax賀老都很認(rèn)同,下班時讀那篇文章,竟然坐車的還坐過站了。大家可以很...

    Edison 評論0 收藏0

發(fā)表評論

0條評論

BicycleWarrior

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<