最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript構(gòu)造函數(shù)與原型、原型鏈?zhǔn)纠斀?/h1>
 更新時(shí)間:2026年03月16日 09:07:11   作者:Hello--_--World  
在JavaScript中,構(gòu)造函數(shù)和原型鏈?zhǔn)菍?shí)現(xiàn)面向?qū)ο缶幊痰暮诵臋C(jī)制,它們共同構(gòu)成了JavaScript的類(lèi)繼承模型,這篇文章主要介紹了JavaScript構(gòu)造函數(shù)與原型、原型鏈的相關(guān)資料,需要的朋友可以參考下

一 構(gòu)造函數(shù)

在 JavaScript 中,構(gòu)造函數(shù)(Constructor)是用于批量生成對(duì)象。雖然 ES6 引入了 class 關(guān)鍵字,但其底層邏輯依然是基于構(gòu)造函數(shù)和原型鏈的。

1 什么是構(gòu)造函數(shù)?

在 JS 中,構(gòu)造函數(shù)本質(zhì)上就是一個(gè)普通的函數(shù),但為了區(qū)分,通常遵循以下約定:

  • 首字母大寫(xiě)(如 function Person() {…})。

  • 使用 new 關(guān)鍵字調(diào)用。

2 new 關(guān)鍵字背后的核心邏輯

當(dāng)你使用 new 調(diào)用函數(shù)時(shí),JS 引擎在后臺(tái)完成了四件事:

  1. 創(chuàng)建一個(gè)新的空對(duì)象。

  2. 將這個(gè)新對(duì)象的原型__proto__指向構(gòu)造函數(shù)的 prototype 屬性。

  3. 將構(gòu)造函數(shù)內(nèi)部的 this 綁定到這個(gè)新對(duì)象上。

  4. 如果函數(shù)沒(méi)有返回其他對(duì)象,則自動(dòng)返回這個(gè)新對(duì)象。

function User(name, age) {
  // 1. 這里的 this 指向新創(chuàng)建的對(duì)象
  this.name = name;
  this.age = age;
  
	//這個(gè) sayHi 函數(shù),是每個(gè)對(duì)象獨(dú)有的,每個(gè)對(duì)象都會(huì)在堆中創(chuàng)建一個(gè)
  this.sayHi = function() {
    console.log(`你好,我是 ${this.name}`); 
  };
  // 4. 隱式返回 this
}

// 實(shí)例化對(duì)象
const user1 = new User("張三", 25);
const user2 = new User("李四", 30);

user1.sayHi(); // 輸出: 你好,我是 張三

2.1原型方法優(yōu)化(性能關(guān)鍵)

在上面的例子中,sayHi 方法直接寫(xiě)在構(gòu)造函數(shù)里。這意味著每創(chuàng)建一個(gè)實(shí)例,都會(huì)在內(nèi)存中復(fù)制一份該函數(shù)。
改進(jìn)方法:將方法寫(xiě)在 prototype上,所有實(shí)例共享同一個(gè)函數(shù)。

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

// 所有 Dog 的實(shí)例都共享這一個(gè)方法,節(jié)省內(nèi)存
Dog.prototype.bark = function() {
  console.log(`${this.name} 在汪汪叫`);
};

const d1 = new Dog("大黃");
const d2 = new Dog("小白");
console.log(d1.bark === d2.bark); // true

2.2 構(gòu)造函數(shù)的返回值

如果構(gòu)造函數(shù)返回的是原始類(lèi)型(數(shù)字、字符串等),會(huì)被忽略,依然返回 this 對(duì)象。

如果構(gòu)造函數(shù)返回的是一個(gè)對(duì)象,則 new 的結(jié)果會(huì)變成那個(gè)返回的對(duì)象。

2.3 強(qiáng)制檢查 new 調(diào)用

如果忘記寫(xiě) new,this 會(huì)指向全局對(duì)象(瀏覽器中是 window),這會(huì)導(dǎo)致 Bug。 可以使用 new.target 來(lái)檢查。

new 本身并不是一個(gè)對(duì)象,它是一個(gè)運(yùn)算符(Operator)(類(lèi)似于 +, -, instanceof, typeof)。 運(yùn)算符不是對(duì)象,因此它沒(méi)有屬性。

你可能看到的 new.target 是 JavaScript 語(yǔ)法中唯一的元屬性。這里的“點(diǎn)”號(hào)并不代表對(duì)象訪(fǎng)問(wèn)屬性,而是一個(gè)特殊的語(yǔ)法結(jié)構(gòu),用來(lái)從運(yùn)算符環(huán)境中提取信息。

補(bǔ)充:為什么叫“元屬性”?

元屬性(Meta Property)是指那些非對(duì)象屬性。除了 new.target,在較新的 JS 規(guī)范中幾乎沒(méi)有類(lèi)似的結(jié)構(gòu)。它存在的唯一目的就是讓函數(shù)內(nèi)部能夠感知到“外部調(diào)用者”是通過(guò)什么方式來(lái)觸發(fā)我的。

function Person(name) {
  if (!new.target) {
    throw new Error("必須使用 new 關(guān)鍵字調(diào)用構(gòu)造函數(shù)");
  }
  this.name = name;
}

2.3.1 new.target 返回的是什么?

new.target 是一個(gè)元屬性(Meta Property)。它不是一個(gè)普通的變量,而是專(zhuān)門(mén)用來(lái)檢測(cè)函數(shù)是否是通過(guò) new 運(yùn)算符調(diào)用的。

  • 如果是通過(guò) new 調(diào)用:new.target 返回該構(gòu)造函數(shù)本身。

  • 如果是普通函數(shù)調(diào)用(如 Person()):new.target 返回 undefined。

它的核心作用:

  1. 強(qiáng)制初始化:確保構(gòu)造函數(shù)不會(huì)被當(dāng)作普通函數(shù)誤用。

  2. 在繼承中識(shí)別子類(lèi):在父類(lèi)構(gòu)造函數(shù)中,new.target 指向的是真正被實(shí)例化的那個(gè)類(lèi)。

class Parent {
  constructor() {
    console.log("當(dāng)前創(chuàng)建實(shí)例的類(lèi)是:", new.target.name);
  }
}

class Child extends Parent {}

new Parent(); // 輸出: "當(dāng)前創(chuàng)建實(shí)例的類(lèi)是: Parent"
new Child();  // 輸出: "當(dāng)前創(chuàng)建實(shí)例的類(lèi)是: Child" (即便是在父類(lèi)構(gòu)造函數(shù)里打印)

3 ES6 Class 寫(xiě)法(現(xiàn)代推薦)

ES6 的 class 只是構(gòu)造函數(shù)的“語(yǔ)法糖”,結(jié)構(gòu)更清晰:

class Animal {
  // 相當(dāng)于以前的構(gòu)造函數(shù)體
  constructor(species) {
    this.species = species;
  }

  // 相當(dāng)于在 Animal.prototype 上定義方法
  eat() {
    console.log(`${this.species} 正在吃東西`);
  }
}

const cat = new Animal("貓");
cat.eat();

二 原型對(duì)象prototype 與 對(duì)象原型__proto__

1 什么是原型對(duì)象與對(duì)象原型?

  • 所有函數(shù)都有個(gè)屬性叫 原型(prototype) ,它是一個(gè)對(duì)象,稱(chēng)之為 原型對(duì)象
  • 原型對(duì)象 中有個(gè)屬性(constructor),它指回函數(shù)本身
    function Pig(name, age) {
      this.name = name
      this.age = age
    }
    
    console.log(Pig.prototype.constructor === Pig); // true

?? 關(guān)系公式:構(gòu)造函數(shù).prototype.constructor === 構(gòu)造函數(shù)

  • 所有對(duì)象 都有個(gè)屬性(__proto__),它也是一個(gè)對(duì)象,并且指向的就是它構(gòu)造函數(shù)原型對(duì)象
    function Pig(name, age) {
      this.name = name
      this.age = age
    }

    const peiqi = new Pig("peiqi", 18)
    console.log(peiqi.__proto === peiqi.prototype); // true

?? 關(guān)系公式: 實(shí)例.__proto__ === 構(gòu)造函數(shù).prototype

2 為什么設(shè)計(jì)原型?有什么好處?

JavaScript 最初被設(shè)計(jì)為一種輕量級(jí)的腳本語(yǔ)言,沒(méi)有傳統(tǒng)類(lèi)的概念。

  • 節(jié)省內(nèi)存:如果沒(méi)有原型,每個(gè)實(shí)例都要在內(nèi)存中存儲(chǔ)一份相同的方法(如 sayHello)。有了原型,方法只需在原型對(duì)象上存一份,所有實(shí)例共用。

  • 數(shù)據(jù)共享與繼承:方便實(shí)現(xiàn)屬性和方法的繼承,修改原型對(duì)象,所有實(shí)例會(huì)立即同步更新。

3 什么是原型鏈?

原型對(duì)象本身也是一個(gè)對(duì)象,它也有自己的對(duì)象原型(構(gòu)造函數(shù).prototype.__proto__

當(dāng)你訪(fǎng)問(wèn)一個(gè)對(duì)象的屬性時(shí),如果對(duì)象本身沒(méi)有這個(gè)屬性,JS 引擎就會(huì)去它的 __proto__(原型對(duì)象)里找。

如果原型對(duì)象也沒(méi)有,就去原型的原型里找,直到找到 Object.prototype 為止。

這種由 __proto__ 層層鏈接形成的鏈?zhǔn)浇Y(jié)構(gòu),就是原型鏈。原型鏈的終點(diǎn)是 null

4 調(diào)用屬性或方法的流程

流程遵循“就近原則”:

  1. 搜索自身:檢查對(duì)象實(shí)例本身是否有該屬性/方法。

  2. 搜索原型:若無(wú),順著 __proto__ 找到原型對(duì)象。

  3. 搜索原型鏈:若原型對(duì)象也沒(méi)有,繼續(xù)向上查找,直到 Object.prototype。

  4. 返回結(jié)果:找到則返回,直到終點(diǎn)還沒(méi)找到則返回 undefined(方法調(diào)用則報(bào)錯(cuò) is not a function)。

5 實(shí)例可以覆蓋原型中的屬性嗎?

可以,但這不是真正的“覆蓋”,而是“屏蔽(Shadowing)”。

如果你給實(shí)例添加了一個(gè)與原型同名的屬性,查找流程會(huì)在第一步(搜索自身)就找到并返回,從而不再去原型上找。原型的屬性依然存在,只是被“擋住”了。刪除實(shí)例上的該屬性后,原型上的屬性會(huì)重新“露出來(lái)”。

總結(jié)

到此這篇關(guān)于JavaScript構(gòu)造函數(shù)與原型、原型鏈的文章就介紹到這了,更多相關(guān)JS構(gòu)造函數(shù)與原型、原型鏈內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺析Javascript的自動(dòng)分號(hào)插入(ASI)機(jī)制

    淺析Javascript的自動(dòng)分號(hào)插入(ASI)機(jī)制

    我們大家都知道在寫(xiě)java和c時(shí),必須要在語(yǔ)句后加分號(hào),否則編譯通不過(guò)。而js不同,存在自動(dòng)分好插入機(jī)制,下文簡(jiǎn)稱(chēng)ASI。它會(huì)給源代碼的 token 流自動(dòng)插入分號(hào)。下面這篇文章我們就來(lái)談?wù)凧avascript的自動(dòng)分號(hào)插入(ASI)機(jī)制。
    2016-09-09
  • JavaScript之AOP編程實(shí)例

    JavaScript之AOP編程實(shí)例

    這篇文章主要介紹了JavaScript的AOP編程,以實(shí)例形式分析了javascript面向切面編程的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • JavaScript六種繼承方式總結(jié)大全

    JavaScript六種繼承方式總結(jié)大全

    JavaScript中最基本的繼承方式,其核心思想是利用原型讓一個(gè)引用類(lèi)型繼承另一個(gè)引用類(lèi)型的屬性和方法,下面這篇文章主要介紹了JavaScript六種繼承方式的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-10-10
  • 小程序?qū)崿F(xiàn)列表倒計(jì)時(shí)功能

    小程序?qū)崿F(xiàn)列表倒計(jì)時(shí)功能

    這篇文章主要為大家詳細(xì)介紹了小程序?qū)崿F(xiàn)列表倒計(jì)時(shí)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • JavaScript中Undefined類(lèi)型的使用

    JavaScript中Undefined類(lèi)型的使用

    JavaScript中,Undefined類(lèi)型是一個(gè)特殊且基礎(chǔ)的數(shù)據(jù)類(lèi)型, 本文就來(lái)詳細(xì)的介紹一下JavaScript中Undefined類(lèi)型的使用,感興趣的可以了解一下
    2026-02-02
  • JS數(shù)組扁平化、去重、排序操作實(shí)例詳解

    JS數(shù)組扁平化、去重、排序操作實(shí)例詳解

    這篇文章主要介紹了JS數(shù)組扁平化、去重、排序操作,結(jié)合實(shí)例形式詳細(xì)分析了JS數(shù)組扁平化、去重、排序等相關(guān)操作原理、實(shí)現(xiàn)技巧與注意事項(xiàng),需要的朋友可以參考下
    2020-02-02
  • 詳解JavaScript中的鏈?zhǔn)秸{(diào)用

    詳解JavaScript中的鏈?zhǔn)秸{(diào)用

    這篇文章主要介紹了JavaScript中的鏈?zhǔn)秸{(diào)用的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)JavaScript,感興趣的朋友可以了解下
    2020-11-11
  • 微信小程序之裁剪圖片成圓形的實(shí)現(xiàn)代碼

    微信小程序之裁剪圖片成圓形的實(shí)現(xiàn)代碼

    最近在開(kāi)發(fā)小程序,產(chǎn)品經(jīng)理提了一個(gè)需求,要求微信小程序換頭像,用戶(hù)剪裁圖片必須是圓形。這篇文章主要介紹了微信小程序之裁剪圖片成圓形 ,需要的朋友可以參考下
    2018-10-10
  • javascript面向?qū)ο髣?chuàng)建對(duì)象的方式小結(jié)

    javascript面向?qū)ο髣?chuàng)建對(duì)象的方式小結(jié)

    這篇文章主要介紹了javascript面向?qū)ο髣?chuàng)建對(duì)象的方式,結(jié)合實(shí)例形式總結(jié)分析了javascript常見(jiàn)的7種創(chuàng)建對(duì)象的方式,需要的朋友可以參考下
    2019-07-07
  • 前端處理文本換行展示4種處理方法

    前端處理文本換行展示4種處理方法

    在處理前端顯示后端傳遞的包含換行符的文本時(shí),可以通過(guò)多種方法實(shí)現(xiàn)換行顯示,這篇文章主要介紹了前端處理文本換行展示4種處理方法,這些方法幫助前端正確展示格式化文本,解決了文本堆疊的問(wèn)題,需要的朋友可以參考下
    2024-10-10

最新評(píng)論

奇台县| 新建县| 抚远县| 肃北| 航空| 元朗区| 桓台县| 新津县| 常德市| 达孜县| 沂源县| 高雄市| 兴城市| 蚌埠市| 铜陵市| 竹山县| 时尚| 民权县| 沅陵县| 温宿县| 白水县| 奉节县| 区。| 北碚区| 长乐市| 化隆| 鹤庆县| 蓝山县| 柳河县| 华安县| 光泽县| 盐源县| 柳林县| 鹤峰县| 苍梧县| 临城县| 英山县| 博乐市| 武城县| 平塘县| 保康县|