成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

關(guān)于原型、原型鏈、和繼承

沈儉 / 1035人閱讀

摘要:根據(jù)定義,沒有原型,并作為這個原型鏈中的最后一個環(huán)節(jié)。偷偷貼在這里再知道了原型原型鏈,那一個對象的過程知道嗎,能手寫一個嗎。

似乎生活中常常會遇到這種情況,你去一家公司面試,前面面的都挺好,你覺得你對基礎(chǔ)算法的了解很好,各種排序,紅黑樹,二叉樹,深度/廣度優(yōu)先算法都答出來了,leetcode上的若干困難題目也都答上來了,然后面試官說,"那么好吧,介紹一下你對原型的看法吧。"

???我頭發(fā)。我leetcode上刷了100天,我費(fèi)勁心思研究了各種算法和數(shù)據(jù)結(jié)構(gòu),你叫我講講原型?

為了應(yīng)對這種情況,本文通過如下代碼展示下js的原型僅供參考。

上CODE
const c = (...v) => console.log(...v);
function People(name, age) {
  this.name = name;
  this.age = age;
}
/*你想這么寫也沒關(guān)系
const People = function(name, age) {
  this.name = name;
  this.age = age;
}
*/
People.prototype.info = function() {
  c(`My name is ${this.name}, my age is ${this.age}.`);
};  // 在原型上定義方法
function Student(name, age, school) {
  People.call(this, ...arguments); 
  this.school = school;
}
Student.prototype = People.prototype;  
// 這里推薦用new People(),直接指定People.prototype會污染People原型,如下結(jié)果
Student.prototype.constructor = Student;  //修正constructor指向
Student.prototype.talk = function() {
  c(`My school is ${this.school}`);
};  // 需要在改變了Student的原型后定義,否則無法獲取到該方法

const xiaoD = new Student("xiaoD", 4, "小星星幼兒園");
xiaoD.info();
xiaoD.talk();
const somebody = new People("somebody", 22);
somebody.talk();
c(xiaoD.__proto__ === Student.prototype);
c(Student.__proto__ === Function.prototype);
c(Function.prototype === Function.__proto__);
c(Function.__proto__ === Object.__proto__);
c(Object.__proto__ === Function.prototype);
c(Object.prototype === Function.prototype.__proto__);
c(Object.prototype.__proto__ === null);

可以先猜一下是什么結(jié)果。。

好吧,不用猜了。結(jié)果如下

My name is xiaoD, my age is 4.
My school is 小星星幼兒園
My school is undefined
true
true
true
true
true
true
true

每個實(shí)例對象( object )都有一個私有屬性(稱之為 proto )指向它的原型對象( prototype )。該原型對象也有一個自己的原型對象( proto ) ,層層向上直到一個對象的原型對象為 null。根據(jù)定義,null 沒有原型,并作為這個原型鏈中的最后一個環(huán)節(jié)。至于誰指誰,應(yīng)該從上面的代碼中就可以清晰的看出來了。這里注意的是只有函數(shù)中才有 prototype 屬性。

類的繼承
class People {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  info() {
    c(`My name is ${this.name}, my age is ${this.age}.`);
  }
}
class Student extends People {
  constructor(name, age, school) {
    super(...arguments);        // 繼承屬性
    this.school = school;
    this.talk = this.talk.bind(this);        // 綁定this
    /* 或者這樣綁定
      this.talk = () => {
      this.info();  // 箭頭函數(shù)中的this在定義時綁定
      c(`My school is ${this.school}`);
    };
      */
  }
  talk() {
    this.info();
    c(`My school is ${this.school}`);
  }
  
}

const xiaoD = new Student("xiaoD", 4, "小星星幼兒園");
xiaoD.talk();
const { talk } = xiaoD;
talk();        // 不綁定this這里會報錯
const somebody = new People("somebody", 22);
somebody.talk();  // 報錯,父類中沒有該方法

這里有三個注意點(diǎn):

父類中不會存在子類的方法(面向?qū)ο罅笤瓌t還記得嗎,開閉,單一職責(zé),依賴倒轉(zhuǎn),里氏置換,知道最少,接口隔離,合成聚合復(fù)用)

上面代碼中,talk方法中的this,默認(rèn)指向Student類的實(shí)例。但是,如果將這個方法提取出來多帶帶使用,this會指向該方法運(yùn)行時所在的環(huán)境(由于 class 內(nèi)部是嚴(yán)格模式,所以 this 實(shí)際指向的是undefined),從而導(dǎo)致找不到info方法而報錯。解決辦法如代碼中所示。

關(guān)于箭頭函數(shù)的this指向問題,眾所周知,普通函數(shù)的this是指向調(diào)用它的那個對象,所以普通函數(shù)可以通過apply,call,bind來改變this的指向。而箭頭函數(shù)中的this是在定義函數(shù)的時候就已經(jīng)確定了,指向外層作用域鏈中的普通函數(shù),若沒有,this則指向undefined。

PS

(那么問題又來了,手寫個apply,call,bind的polyfill吧)

const obj = {
  name: "xiaoD"
};
const fn = function(...args) {
  c(this.name, ...args);
};
Function.prototype.myApply = function(obj, [...args]) {
  return this.call(obj, ...args);
};
fn.myApply(obj, ["真", "棒"]);        // xiaoD 真 棒
fn.apply(obj, ["真", "棒"]);            // xiaoD 真 棒

拿走,不謝。

Function.prototype.myApply = function(obj, [...args]) {
  obj.fn = this;
  let ret = obj.fn(...args);
  delete obj.fn;
  return ret;
}; 
Function.prototype.myBind = function(obj) {
  obj.fn = this;
  return function(...args) {
    return obj.fn(...args);
  };
};
// 偷偷貼在這里
再PS

知道了原型、原型鏈,那new一個對象的過程知道嗎,能手寫一個嗎。

new一個對象的過程大概分成三步:

新建一個空對象

改變原型鏈指向,調(diào)用構(gòu)造函數(shù)

返回這個新對象

const myNew = function(fn, ...args) {
  let obj = {};
  obj.__proto__ = fn.prototype;
  let ret = fn.call(obj, ...args);
  return ret ? ret : obj;
};
function People(name, age) {
  this.name = name;
  this.age = age;
}
let xiaoD = myNew(People, "xiaoD", 4);
let xiaoY = new People("xiaoY", 4);            // 可以對比一下,看看兩者區(qū)別

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/109276.html

相關(guān)文章

  • 關(guān)于構(gòu)造函數(shù)、原型原型、多種方式繼承

    摘要:可以看出這個構(gòu)造函數(shù)是由創(chuàng)建出來的,而我們看下的隱式原型,竟然是指向了的原型,也就是也是由創(chuàng)建出來的。例如,其他構(gòu)造函數(shù)的原型將覆蓋屬性并提供自己的方法。將構(gòu)造函數(shù)的執(zhí)行對象賦給這個空對象并且執(zhí)行。把對象的隱式原型指向構(gòu)造函數(shù)的原型。 構(gòu)造函數(shù)與實(shí)例對象 又是這個經(jīng)典的問題,嗯,我先來寫個構(gòu)造函數(shù),然后實(shí)例化一個對象看看。 function Person(name) { this....

    zxhaaa 評論0 收藏0
  • 關(guān)于javascript中的原型原型

    摘要:先來一個構(gòu)造函數(shù)構(gòu)造一個人類實(shí)例化一個對象看看的名字是什么打印結(jié)果先說一個前提只要是函數(shù),就會有一個屬性,可以理解為子代的原型遺傳基因只要是對象,就會有一個方法,可以理解為向上尋找原型的方法。 關(guān)于javascript中的原型和原型鏈 我GitHub上的菜鳥倉庫地址: 點(diǎn)擊跳轉(zhuǎn)查看其他相關(guān)文章 文章在我的博客上的地址: 點(diǎn)擊跳轉(zhuǎn) ? ? ? ? 關(guān)于javascript中的原型和原...

    SmallBoyO 評論0 收藏0
  • 原型是什么?關(guān)于原型中constructor、prototype及__proto__之間關(guān)系的認(rèn)

    摘要:的隱式原型是母,母是由構(gòu)造函數(shù)構(gòu)造的,但函數(shù)的隱式原型又是。。。??赡苁强紤]到它也是由構(gòu)造函數(shù)生成的吧,所以返回的值也是。 showImg(https://segmentfault.com/img/bVyLk0); 首先,我們暫且把object類型和function類型分開來,因?yàn)?function是一個特殊的對象類型,我們這里這是便于區(qū)分,把function類型單獨(dú)拿出來。順便一提,...

    kaka 評論0 收藏0
  • 【面試系列】之二:關(guān)于js原型

    摘要:之二關(guān)于原型開篇我記得初學(xué)時,最難懂的概念就是的原型,而且這個概念在筆試面試中常常提到,因此今天我們把這個概念拿出來,好好聊一聊。 之二:關(guān)于js原型 1. 開篇 我記得初學(xué)js時,最難懂的概念就是js的原型,而且這個概念在筆試面試中常常提到,因此今天我們把這個概念拿出來,好好聊一聊。 在仔細(xì)講解之前,我們先來看一道題,這道題來自JavaScript高級程序設(shè)計中原型鏈那一節(jié): fun...

    _ang 評論0 收藏0
  • 詳解js中的繼承(二)

    摘要:寄生組合式繼承終于寫到最后一個繼承了,我們在之前講了種繼承方式,分別是原型鏈,借用構(gòu)造函數(shù)繼承,組合繼承,原型式繼承,寄生式繼承,其中,前三種聯(lián)系比較緊密,后面兩種也比較緊密,而我們要講的最后一種,是和組合繼承還有寄生式繼承有關(guān)系的。 前言 趁周末結(jié)束之前趕緊先把坑填上。上回我們說到了原型鏈,并且留下了幾個思考題,先把答案公布一下。 在最后一個例子里,console.log(b1.c...

    evin2016 評論0 收藏0
  • 關(guān)于javascript的原型原型,看我就夠了(二)

    摘要:原文鏈接關(guān)于的原型和原型鏈,看我就夠了一參考鏈接闖關(guān)記之原型及原型鏈之原型與原型鏈一篇文章帶你理解原型和原型鏈徹底理解原型鏈一的默認(rèn)指向圖解和的三角關(guān)系原型和原型鏈三張圖搞懂的原型對象與原型鏈 溫故 創(chuàng)建對象的三種方式 通過對象直接量 通過new創(chuàng)建對象 通過Object.create() js中對象分為兩種 函數(shù)對象 普通對象 仔細(xì)觀察如下代碼 function Foo(na...

    eccozhou 評論0 收藏0

發(fā)表評論

0條評論

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