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

詳解JavaScript的原型與原型鏈

 更新時(shí)間:2022年03月18日 15:38:20   作者:赤藍(lán)紫  
這篇文章主要為大家詳細(xì)介紹了JavaScript原型與原型鏈,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助

詳解原型與原型鏈

其實(shí),剛開(kāi)始學(xué)JavaScript時(shí),就有學(xué)過(guò)原型與原型鏈的相關(guān)知識(shí)了,只是當(dāng)時(shí)還沒(méi)有養(yǎng)成寫(xiě)筆記的習(xí)慣,導(dǎo)致現(xiàn)在已經(jīng)忘的七七八八了。

這邊文章真是花了很多心思,寫(xiě)了兩天,看了很多篇篇博文,其中有小參考的,有解決一點(diǎn)疑惑的,但是最后只標(biāo)注了一篇幫助最大的。

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

實(shí)例的構(gòu)造函數(shù)屬性(constructor)指向其構(gòu)造函數(shù)

function Person(name) {
  this.name = name
}
const person = new Person('clz')
console.log(person.constructor === Person)    // true

實(shí)例的構(gòu)造函數(shù)并不是自身屬性,而是從原型對(duì)象上繼承的屬性

function Person(name) {
  this.name = name
}
const person = new Person('clz')
console.log(person.constructor === Person)    // true
console.log(Person.prototype.constructor === Person)    // true
console.log(person.hasOwnProperty('constructor'))     // false:constructor屬性并不是實(shí)例自身的屬性,而是繼承來(lái)的

原型對(duì)象 

  • __proto__(隱式原型):每個(gè)對(duì)象(除了null)都具有的屬性,該屬性指向該對(duì)象的原型
  • prototype(顯式原型):只有函數(shù)對(duì)象才有的屬性,該屬性指向函數(shù)的原型對(duì)象

來(lái)看來(lái)看

const arr = [1, 2, 3]
const obj = {
  name: 'clz'
}
function add(a, b) {
  return a + b
}
console.log(arr)
console.log(obj)
console.log(add)

image-20220314161614197

紅框框中的[[prototype]]__proto__意義相同,都是指對(duì)象的內(nèi)部屬性

而所有函數(shù)都擁有prototype屬性,所以可以通過(guò)f.prototype得到,那么自然也不需要通過(guò)[[prototype]]顯示出來(lái)(畢竟prototype是顯式原型,而__proto__是隱式原型,好吧,這是我猜的)

image-20220314162705526

箭頭函數(shù)沒(méi)有prototype屬性

訪問(wèn)原型

通過(guò)實(shí)例對(duì)象訪問(wèn)原型對(duì)象有 3 種方法

  • obj.__proto__
  • obj.constructor.prototype
  • Object.getPrototypeOf(obj)
function Person(name) {
  this.name = name
}
const person = new Person('clz')
const proto1 = person.__proto__
const proto2 = person.constructor.prototype
const proto3 = Object.getPrototypeOf(person)
const proto = Person.prototype    // 原型
console.log(proto1 === proto)     // true: 第一種方法
console.log(proto2 === proto)     // true: 第二種方法
console.log(proto3 === proto)     // true: 第三種方法

比較安全的做法是Object.getPrototypeOf(obj)

以下部分會(huì)涉及一丟丟原型鏈的知識(shí)(如果沒(méi)看懂,可以看下原型鏈再來(lái)看)

  • __proto__屬性是私有屬性,存在瀏覽器兼容性問(wèn)題,缺乏非瀏覽器環(huán)境的支持
  • 如果obj的constructor屬性被覆蓋,那么obj.constructor.prototype將會(huì)失效。(因?yàn)閛bj自身是沒(méi)有constructor屬性的,是通過(guò)原型鏈去它的原型上獲取constructor屬性,所以覆蓋該屬性時(shí),將不會(huì)再去原型鏈上查找)
function Person(name) {
  this.name = name
}
function Temp(name) {
  this.name = name
}
const person = new Person('clz')
person.constructor = Temp
const proto = Person.prototype    // 原型
console.log(person.__proto__ === proto)     // true: 第一種方法
console.log(person.constructor.prototype === proto)     // false: 第二種方法
console.log(Object.getPrototypeOf(person) === proto)     // true: 第三種方法

設(shè)置原型

設(shè)置原型對(duì)象有 3 種方法

  • obj.__proto__=prototypeObj
  • Object.setPrototypeOf(obj, prototypeObj)
  • Object.create(prototypeObj)
const proto = {   // 原型對(duì)象
  name: 'prototype'
}
// 第一種方法
const obj1 = {}
obj1.__proto__ = proto    // 設(shè)置原型
console.log(obj1.name)          // prototype
console.log(obj1.__proto__ === proto)   // true
// 第二種方法
const obj2 = {}
Object.setPrototypeOf(obj2, proto)    // 設(shè)置原型
console.log(obj2.name)          // prototype
console.log(obj2.__proto__ === proto)   // true
// 第三種方法
const obj3 = Object.create(proto)   // 創(chuàng)建對(duì)象并設(shè)置原型
console.log(obj3.name)          // prototype
console.log(obj3.__proto__ === proto)   // true

檢測(cè)原型

使用obj1.isPrototypeOf(obj2)方法判斷obj1是否為·obj2的原型

const proto = {   // 原型對(duì)象
  name: 'prototype'
}
const proto1 = {
  name: 'prototype'
}
const obj = {}
obj.__proto__ = proto    // 設(shè)置原型
console.log(proto.isPrototypeOf(obj))   // true
console.log(Object.prototype.isPrototypeOf(obj))  // true
console.log(proto1.isPrototypeOf(obj))  // false

prototype、__proto__、constructor之間的關(guān)系

image-20220314170210850

function Person(name) {
  this.name = name
}
const person = new Person('clz')
console.log(person.__proto__ === Person.prototype)		// true:因?yàn)閯?chuàng)建person對(duì)象的構(gòu)造函數(shù)是Person,所以person對(duì)象的隱式原型(__proto__)指向Person函數(shù)的原型(prototype)
console.log(Person.prototype.constructor === Person)	// true

同一個(gè)構(gòu)造函數(shù)創(chuàng)建的多個(gè)實(shí)例的原型是同一個(gè)

function Person(name) {
   this.name = name
 }
 const person1 = new Person('clz')
 const person2 = new Person('clz')
 console.log(person1 === person2)    // false: 不是同一個(gè)對(duì)象
 console.log(person1.__proto__ === person2.__proto__)  // true:同一個(gè)構(gòu)造函數(shù)創(chuàng)建的實(shí)例對(duì)象的原型是同一個(gè)

原型鏈

由上面的知識(shí)可以知道,實(shí)例對(duì)象具有屬性__proto__,會(huì)指向原型對(duì)象。而原型對(duì)象也是對(duì)象,所以也會(huì)有屬性__proto__,也會(huì)繼續(xù)指向它的原型對(duì)象。

實(shí)例對(duì)象在查找屬性時(shí),如果查找不到,就會(huì)沿著__proto__去它的原型上查找,還找不到,則繼續(xù)去原型的原型上查找,直到找到或到最頂層為止。這就是原型鏈的概念。

對(duì)象本身的方法(第一層:把方法當(dāng)成屬性)

function Person(name) {
  this.name = name
  this.listenMusic = function () {
    console.log('聽(tīng)音樂(lè)')
  }
}
const person = new Person('clz')
console.log(person)
console.log('實(shí)例對(duì)象本身是否有l(wèi)istenMusic方法', person.hasOwnProperty('listenMusic'))
person.listenMusic()

image-20220315094508947

對(duì)象的原型上添加方法(第二層)

function Person(name) {
  this.name = name
}
Person.prototype.listenMusic = function () {
  console.log('聽(tīng)音樂(lè)')
}
const person = new Person('clz')
console.log(person)
console.log('實(shí)例對(duì)象本身是否有l(wèi)istenMusic方法', person.hasOwnProperty('listenMusic'))
person.listenMusic()

image-20220314183755250

原型的原型上的方法(第三層)

function Person(name) {
  this.name = name
}
Person.prototype.__proto__.listenMusic = function () {
  console.log('聽(tīng)音樂(lè)')
}
const person = new Person('clz')
console.log(person)
person.listenMusic()

image-20220314184300125

但是呢,沒(méi)法玩第四層,因?yàn)橐呀?jīng)到頂了(Object.prototype沒(méi)有原型(原型為null))

function Person(name) {
  this.name = name
}
Person.prototype.__proto__.__proto__.listenMusic = function () {
  console.log('聽(tīng)音樂(lè)')
}
const person = new Person('clz')
console.log(person)
person.listenMusic()

image-20220314184424877

person -> Person.prototype -> Object.prototype -> null

那么,這里就來(lái)看看第三層是不是真的是Object.prototype

function Person(name) {
  this.name = name
}
Person.prototype.__proto__.listenMusic = function () {
  console.log('聽(tīng)音樂(lè)')
}
const person = new Person('clz')
console.log(person)
console.log(Person.prototype.__proto__ === person.__proto__.__proto__)
console.log(person.__proto__.__proto__ === Object.prototype)   // 這里就是判斷處
person.listenMusic()

image-20220315095211650

發(fā)現(xiàn),確實(shí)如此。

下面這張圖就是原型鏈的簡(jiǎn)單圖(找不到是在哪里截的圖了,侵刪)

image-20220314233252631

原型鏈的作用

為對(duì)象設(shè)置默認(rèn)值

利用原型為對(duì)象設(shè)置默認(rèn)值。當(dāng)原型屬性與私有屬性同名時(shí),刪除私有屬性之后,可以訪問(wèn)原型屬性,即可以把原型屬性值作為初始化默認(rèn)值。

function Person(name) {
  this.name = name
}
Person.prototype.name = '赤藍(lán)紫'
const person = new Person('clz')
console.log(person.name)    // clz
delete person.name
console.log(person.name)    // 赤藍(lán)紫

繼承

繼承內(nèi)容部分之后單獨(dú)寫(xiě)。

擴(kuò)展原型方法

Array.prototype.test = function () {
  console.log('擴(kuò)展原型方法: 有風(fēng)險(xiǎn)')
}
const arr = [1, 2, 3]
arr.test()    // 擴(kuò)展原型方法: 有風(fēng)險(xiǎn)

typeof

typeof是判斷類(lèi)型時(shí)大多數(shù)人的選擇(當(dāng)然也包括我啦),但是,判斷非基本數(shù)據(jù)類(lèi)型(function除外)時(shí),只能得到Object。(null也是,但是null這個(gè)屬于是歷史遺留bug了)。

js 在底層存儲(chǔ)變量的時(shí)候,會(huì)在變量的機(jī)器碼的低位1-3位存儲(chǔ)其類(lèi)型信息

  • 000:對(duì)象
  • 010:浮點(diǎn)數(shù)
  • 100:字符串
  • 110:布爾
  • 1:整數(shù)

null:所有機(jī)器碼均為0

undefined:用 −2^30 整數(shù)來(lái)表示

symbolbigint是后來(lái)新增的數(shù)據(jù)類(lèi)型

const num = 123
const str = 'hello'
const bool = true
const n = null
const u = undefined
const sym = Symbol(1)
const big = BigInt(123)
const fun = () => console.log(1)
console.log(typeof num)   // number
console.log(typeof str)   // string
console.log(typeof bool)  // boolean
console.log(typeof n)     // object
console.log(typeof u)     // undefined
console.log(typeof sym)   // symbol			
console.log(typeof big)   //bigint
console.log(typeof fun)   //function

function除外的非基本數(shù)據(jù)類(lèi)型

let arr = []
let obj = {
  name: 'clz'
}
let set = new Set([1, 2, 4])
console.log(typeof arr)
console.log(typeof obj)
console.log(typeof set) 

清一色object

通過(guò)Object.prototype.toString.call(obj)來(lái)識(shí)別對(duì)象類(lèi)型。會(huì)返回"[object Type]"來(lái)告訴你所指對(duì)象的類(lèi)型

let arr = []
let obj = {
  name: 'clz'
}
let set = new Set([1, 2, 4])
console.log(Object.prototype.toString.call(arr))  // [object Array]
console.log(Object.prototype.toString.call(obj))  // [object Object]
console.log(Object.prototype.toString.call(set))  // [object Set]

instanceof

instanceof只要右邊變量的 prototype 在左邊變量的原型鏈上,就會(huì)返回true

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

const person = new Person('clz')
console.log(person instanceof Person)   // true
console.log(person instanceof Object)   // true
console.log(person instanceof Test)     // false

普通對(duì)象與函數(shù)對(duì)象

  • 所有的函數(shù)都是通過(guò)new Function()來(lái)創(chuàng)建的,即是函數(shù)對(duì)象
  • 其他的都是普通對(duì)象
function fn1() { }
const fn2 = function () { }
const fn3 = () => { }
const fn4 = new Function()
console.log(typeof fn1)       //function
console.log(typeof fn2)       //function
console.log(typeof fn3)       //function
console.log(typeof fn4)       //function

const obj1 = {}
const obj2 = new Object()
const obj3 = new fn1()
console.log(typeof obj1);     //object 
console.log(typeof obj2);     //object 
console.log(typeof obj3);     //object

上面的例子中,fn1fn2、fn3fn4是函數(shù)對(duì)象,obj1、obj2obj3是普通對(duì)象

  • Object是構(gòu)造函數(shù),即也是函數(shù),所以Object也是函數(shù)對(duì)象,相當(dāng)于Function的實(shí)例,即Object.__proto__ === Function.prototype
  • Object.prototypeObject構(gòu)造函數(shù)的原型,處于原型鏈的頂端,Object.prototype.__proto__已經(jīng)沒(méi)有可以指向的上層原型,因此其值為null
console.log(typeof Object)    // function
console.log(Object.__proto__ === Function.prototype)    // true
console.log(Object.prototype.__proto__)   // null
  • Function.prototypeFunction的原型,是所有函數(shù)對(duì)象的原型
  • Function.prototype是一個(gè)普通對(duì)象,所以Function.prototype.__proto__ === Object.prototype
  • Function函數(shù)不通過(guò)任何東西創(chuàng)建,JS引擎啟動(dòng)時(shí),添加到內(nèi)存中,所以**Function.__proto__ === Function.prototype**
console.log(typeof Function)    // function
console.log(Function.prototype.__proto__ === Object.prototype)    // true
console.log(Function.__proto__ === Function.prototype)   // true

經(jīng)典原型鏈圖

img

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容! 

相關(guān)文章

  • Active控件問(wèn)題小結(jié)(附解決辦法)

    Active控件問(wèn)題小結(jié)(附解決辦法)

    這篇文章主要介紹了Active控件問(wèn)題小結(jié)(附解決辦法)的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • 獲取div編輯框,textarea,input text的光標(biāo)位置 兼容IE,F(xiàn)F和Chrome的方法介紹

    獲取div編輯框,textarea,input text的光標(biāo)位置 兼容IE,F(xiàn)F和Chrome的方法介紹

    獲取div編輯框,textarea,input text的光標(biāo)位置 兼容IE,F(xiàn)F和Chrome的方法介紹,有需求的朋友可以參考
    2012-11-11
  • 萬(wàn)字詳解JavaScript手寫(xiě)一個(gè)Promise

    萬(wàn)字詳解JavaScript手寫(xiě)一個(gè)Promise

    這篇文章主要介紹了萬(wàn)字詳解JavaScript手寫(xiě)一個(gè)Promise,Promise就是一個(gè)類(lèi),在執(zhí)行這個(gè)類(lèi)的時(shí)候,需要傳遞一個(gè)執(zhí)行器(回調(diào)函數(shù))進(jìn)去,執(zhí)行器會(huì)立即執(zhí)行
    2022-07-07
  • 小程序自定義輪播圖圓點(diǎn)組件

    小程序自定義輪播圖圓點(diǎn)組件

    這篇文章主要為大家詳細(xì)介紹了小程序自定義輪播圖圓點(diǎn)組件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • JS字符串補(bǔ)全方法padStart()和padEnd()

    JS字符串補(bǔ)全方法padStart()和padEnd()

    這篇文章主要介紹了JS字符串補(bǔ)全方法padStart()和padEnd(),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • JavaScript一元正號(hào)運(yùn)算符示例代碼

    JavaScript一元正號(hào)運(yùn)算符示例代碼

    這篇文章主要給大家介紹了關(guān)于JavaScript一元正號(hào)運(yùn)算符的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用JavaScript具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • js簡(jiǎn)單實(shí)現(xiàn)點(diǎn)擊左右運(yùn)動(dòng)的方法

    js簡(jiǎn)單實(shí)現(xiàn)點(diǎn)擊左右運(yùn)動(dòng)的方法

    這篇文章主要介紹了js簡(jiǎn)單實(shí)現(xiàn)點(diǎn)擊左右運(yùn)動(dòng)的方法,實(shí)例分析了javascript實(shí)現(xiàn)左右運(yùn)動(dòng)的相關(guān)要點(diǎn)與技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04
  • JS/FLASH實(shí)現(xiàn)復(fù)制代碼到剪貼板(兼容所有瀏覽器)

    JS/FLASH實(shí)現(xiàn)復(fù)制代碼到剪貼板(兼容所有瀏覽器)

    使用javascript來(lái)寫(xiě)復(fù)制到剪貼板的代碼,一般都是瀏覽器不兼容的。所以采用flash的方式,模擬一個(gè)層,再來(lái)復(fù)制,就可以做到全部瀏覽器都適用,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下哈
    2013-05-05
  • layui table去掉右側(cè)滑動(dòng)條的實(shí)現(xiàn)方法

    layui table去掉右側(cè)滑動(dòng)條的實(shí)現(xiàn)方法

    今天小編就為大家分享一篇layui table去掉右側(cè)滑動(dòng)條的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-09-09
  • Json解析的方法小結(jié)

    Json解析的方法小結(jié)

    本文給大家?guī)?lái)了json解析方法小結(jié)的知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-06-06

最新評(píng)論

闵行区| 永德县| 丁青县| 城固县| 佛山市| 根河市| 黄龙县| 南陵县| 裕民县| 措勤县| 桓台县| 房山区| 卢氏县| 城固县| 杭锦旗| 桃江县| 乐都县| 寿光市| 桐梓县| 财经| 宁化县| 海南省| 阜新| 闽侯县| 亚东县| 长治市| 襄汾县| 凤台县| 寻乌县| 繁昌县| 延寿县| 土默特左旗| 如东县| 安达市| 开鲁县| 陈巴尔虎旗| 澄迈县| 祁阳县| 砀山县| 凤城市| 体育|