欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解JavaScript的原型與原型鏈

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

詳解原型與原型鏈

其實,剛開始學JavaScript時,就有學過原型與原型鏈的相關知識了,只是當時還沒有養(yǎng)成寫筆記的習慣,導致現(xiàn)在已經(jīng)忘的七七八八了。

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

構造函數(shù)

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

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

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

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屬性并不是實例自身的屬性,而是繼承來的

原型對象 

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

來看來看

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__意義相同,都是指對象的內(nèi)部屬性

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

image-20220314162705526

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

訪問原型

通過實例對象訪問原型對象有 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)

以下部分會涉及一丟丟原型鏈的知識(如果沒看懂,可以看下原型鏈再來看)

  • __proto__屬性是私有屬性,存在瀏覽器兼容性問題,缺乏非瀏覽器環(huán)境的支持
  • 如果obj的constructor屬性被覆蓋,那么obj.constructor.prototype將會失效。(因為obj自身是沒有constructor屬性的,是通過原型鏈去它的原型上獲取constructor屬性,所以覆蓋該屬性時,將不會再去原型鏈上查找)
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: 第三種方法

設置原型

設置原型對象有 3 種方法

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

檢測原型

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

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

prototype、__proto__、constructor之間的關系

image-20220314170210850

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

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

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

原型鏈

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

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

對象本身的方法(第一層:把方法當成屬性)

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

image-20220315094508947

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

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

image-20220314183755250

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

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

image-20220314184300125

但是呢,沒法玩第四層,因為已經(jīng)到頂了(Object.prototype沒有原型(原型為null))

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

image-20220314184424877

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

那么,這里就來看看第三層是不是真的是Object.prototype

function Person(name) {
  this.name = name
}
Person.prototype.__proto__.listenMusic = function () {
  console.log('聽音樂')
}
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),確實如此。

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

image-20220314233252631

原型鏈的作用

為對象設置默認值

利用原型為對象設置默認值。當原型屬性與私有屬性同名時,刪除私有屬性之后,可以訪問原型屬性,即可以把原型屬性值作為初始化默認值。

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

繼承

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

擴展原型方法

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

typeof

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

js 在底層存儲變量的時候,會在變量的機器碼的低位1-3位存儲其類型信息

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

null:所有機器碼均為0

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

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

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ù)類型

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

通過Object.prototype.toString.call(obj)來識別對象類型。會返回"[object Type]"來告訴你所指對象的類型

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 在左邊變量的原型鏈上,就會返回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

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

  • 所有的函數(shù)都是通過new Function()來創(chuàng)建的,即是函數(shù)對象
  • 其他的都是普通對象
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

上面的例子中,fn1、fn2fn3、fn4是函數(shù)對象,obj1、obj2、obj3是普通對象

  • Object是構造函數(shù),即也是函數(shù),所以Object也是函數(shù)對象,相當于Function的實例,即Object.__proto__ === Function.prototype
  • Object.prototypeObject構造函數(shù)的原型,處于原型鏈的頂端,Object.prototype.__proto__已經(jīng)沒有可以指向的上層原型,因此其值為null
console.log(typeof Object)    // function
console.log(Object.__proto__ === Function.prototype)    // true
console.log(Object.prototype.__proto__)   // null
  • Function.prototypeFunction的原型,是所有函數(shù)對象的原型
  • Function.prototype是一個普通對象,所以Function.prototype.__proto__ === Object.prototype
  • Function函數(shù)不通過任何東西創(chuàng)建,JS引擎啟動時,添加到內(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

總結

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

相關文章

  • FF下zoom的替代方案 單位em

    FF下zoom的替代方案 單位em

    css 屬性zoom是ie私有屬性 在FF中(或者說僅實現(xiàn)CSS標準的其他瀏覽器中)無法使用,一直在網(wǎng)上搜索它的替代方案,但沒有收獲,后來聽群里有朋友說em或可解決此問題,經(jīng)過研究和測試,發(fā)現(xiàn)果然可以解決。
    2008-08-08
  • JavaScript限定范圍拖拽及自定義滾動條應用(3)

    JavaScript限定范圍拖拽及自定義滾動條應用(3)

    這篇文章主要介紹了JavaScript限定范圍拖拽及自定義滾動條應用的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • js中substring和substr的定義和用法

    js中substring和substr的定義和用法

    這篇文章主要介紹了js中substring和substr的定義和用法,需要的朋友可以參考下
    2014-05-05
  • 利用JS屏蔽頁面中的Enter按鍵提交表單的方法

    利用JS屏蔽頁面中的Enter按鍵提交表單的方法

    下面小編就為大家?guī)硪黄肑S屏蔽頁面中的Enter按鍵提交表單的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • js實現(xiàn)的牛頓擺效果

    js實現(xiàn)的牛頓擺效果

    本文給大家分享的是使用javascript實現(xiàn)牛頓排球的特效,非常不錯,這里推薦給大家,有相同需求的小伙伴能夠參考下。
    2015-03-03
  • JavaScript實現(xiàn)經(jīng)緯度轉換成地址功能

    JavaScript實現(xiàn)經(jīng)緯度轉換成地址功能

    這篇文章主要介紹了JavaScript實現(xiàn)經(jīng)緯度轉換成地址,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-03-03
  • Bootstrap框架下下拉框select搜索功能

    Bootstrap框架下下拉框select搜索功能

    這篇文章主要為大家詳細介紹了Bootstrap框架下下拉框select搜索功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • 如何在JavaScript中等分數(shù)組的實現(xiàn)

    如何在JavaScript中等分數(shù)組的實現(xiàn)

    這篇文章主要介紹了如何在JavaScript中等分數(shù)組的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • Openlayers繪制地圖標注

    Openlayers繪制地圖標注

    這篇文章主要為大家詳細介紹了Openlayers繪制地圖標注,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09

最新評論