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

資訊專欄INFORMATION COLUMN

關于原型、原型鏈、和繼承

沈儉 / 1024人閱讀

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

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

???我頭發。我leetcode上刷了100天,我費勁心思研究了各種算法和數據結構,你叫我講講原型?

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

上CODE
const c = (...v) => console.log(...v);
function People(name, age) {
  this.name = name;
  this.age = age;
}
/*你想這么寫也沒關系
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原型,如下結果
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);

可以先猜一下是什么結果。。

好吧,不用猜了。結果如下

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

每個實例對象( object )都有一個私有屬性(稱之為 proto )指向它的原型對象( prototype )。該原型對象也有一個自己的原型對象( proto ) ,層層向上直到一個對象的原型對象為 null。根據定義,null 沒有原型,并作為這個原型鏈中的最后一個環節。至于誰指誰,應該從上面的代碼中就可以清晰的看出來了。這里注意的是只有函數中才有 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();  // 箭頭函數中的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();  // 報錯,父類中沒有該方法

這里有三個注意點:

父類中不會存在子類的方法(面向對象六大原則還記得嗎,開閉,單一職責,依賴倒轉,里氏置換,知道最少,接口隔離,合成聚合復用)

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

關于箭頭函數的this指向問題,眾所周知,普通函數的this是指向調用它的那個對象,所以普通函數可以通過apply,call,bind來改變this的指向。而箭頭函數中的this是在定義函數的時候就已經確定了,指向外層作用域鏈中的普通函數,若沒有,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一個對象的過程大概分成三步:

新建一個空對象

改變原型鏈指向,調用構造函數

返回這個新對象

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);            // 可以對比一下,看看兩者區別

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109276.html

相關文章

  • 關于構造函數、原型原型、多種方式繼承

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

    zxhaaa 評論0 收藏0
  • 關于javascript中的原型原型

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

    SmallBoyO 評論0 收藏0
  • 原型是什么?關于原型中constructor、prototype及__proto__之間關系的認

    摘要:的隱式原型是母,母是由構造函數構造的,但函數的隱式原型又是。。。。可能是考慮到它也是由構造函數生成的吧,所以返回的值也是。 showImg(https://segmentfault.com/img/bVyLk0); 首先,我們暫且把object類型和function類型分開來,因為 function是一個特殊的對象類型,我們這里這是便于區分,把function類型單獨拿出來。順便一提,...

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

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

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

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

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

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

    eccozhou 評論0 收藏0

發表評論

0條評論

沈儉

|高級講師

TA的文章

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