JS 總結之原型

圖片描述

在 JavaScript 中,函數也是屬於對象,能夠像其餘對象同樣訪問屬性,其中便有一個屬性叫原型 prototype,值爲一個對象,默認,原型有一個 constructor 屬性,指向了構造函數自己git

function Person () {
  return 'hi'
}
Person.prototype // {constructor: ƒ}
Person.prototype.constructor // ƒ Person() {}

用圖來表示:github

圖片描述

咱們能夠對這個屬性進行操做,但這個屬性,只有在對函數進行構造調用的時候纔會起做用編程

🙂 爲原型添加屬性和方法

function Person (name) {
  this.name = name
}
Person.prototype.smart = true
Person.prototype.run = function () {
  console.log('running')
}

// 或者一次性添加

Person.prototype = {
  smart: true,
  run() {
    console.log('running')
  }
}

😳 使用

// ...
let a = new Person('a')
a.name // a
a.smart // true
a.run() // running

😋 instanceof

用來檢測構造函數的原型是否存在於實例的原型鏈函數

// ...
let b = new Person('b')
b instanceof Person // true
b instanceof Object // true

😍 hasOwnPrototype

該方法來判斷是否自身屬性,如:this

function Person () {
  this.name = 'Jon'
}
Person.prototype.name = 'people'
Person.prototype.age = 18
let jon = new Person()
jon.hasOwnProperty('name') // true
jon.hasOwnProperty('age') // false

age 爲原型上的屬性,因此爲 falsespa

😟 isPrototypeOf

該方法來判斷對象是不是另外一個對象的原型,如:prototype

let base = {
  name: 'people',
  age: 18
}
function Person () {
  this.name = 'Jon'
}
Person.prototype = base
let jon = new Person()
base.isPrototypeOf(jon) // true

😯 getPrototypeOf

當不知道對象的原型具體是哪一個的時候,可使用該方法來判斷,如:3d

let base = {
  name: 'people',
  age: 18
}
function Person () {
  this.name = 'Jon'
}
Person.prototype = base
let jon = new Person()
Object.getPrototypeOf(jon) // { name: 'people', age: 18 }

🙃 _ _proto_ _

引用《MDN _ _proto_ _ 》 的解釋:code

Object.prototype 的 _ _proto_ _ 屬性是一個訪問器屬性(一個 getter 函數和一個 setter 函數), 暴露了經過它訪問的對象的內部原型 (一個對象或 null)。

也就是說,每一個對象都有一個該屬性,便攜訪問原型對象,直指原型對象:對象

let base = {
  name: 'people',
  age: 18
}
function Person () {
  this.name = 'Jon'
}
Person.prototype = base
let jon = new Person()
jon.__proto__ // { name: 'people', age: 18 }

用圖來表示:

圖片描述

與 prototype 不一樣的是,_ _proto_ _ 是對象的屬性,prototype 是構造函數的屬性

😦【ES5】Object.create(..)

該方法建立一個新對象,使用現有的對象來提供新建立的對象的 _ _proto_ _

let base = {
  name: 'people',
  age: 18
}
let jon = Object.create(base)
jon.__proto__ // { name: 'people', age: 18 }

😇 原型鏈

當訪問對象的一個屬性時,js 引擎會遍歷自身對象的屬性,若是找不到,便會去原型上查找該屬性,若是仍是找不到,便會繼續查找原型的屬性,直到到 Object 原型

因爲原型是一個對象,是對象便會有一個原型,有原型說明存在構造函數,如 Person 例子,查看原型的構造函數是啥:

// ...
Person.prototype.__proto__.constructor // ƒ Object() { [native code] }

Person.prototype.__proto__.constructor === Object // true

說明 ObjectPerson 原型 的構造函數

說明 Person 原型_ _proto_ _ 會指向 Object.prototype,由於 _ _proto_ _ 能快捷訪問原型:

// ...
Object.getPrototypeOf(jon.__proto__) === Object.prototype // true
// 或者
jon.__proto__.__proto__ === Object.prototype // true
// 或者
Person.prototype.__proto__ === Object.prototype // true

用圖表示就是:

圖片描述

舉個例子:

// ...
let a = new Person('a')
a.toString() // "[object Object]"

Person 函數和原型上都沒有 toString 方法,因此只能調用 Object 上的 toString 方法。

注意:基於同一個構造函數生成的對象,共享函數的原型,如:

// ...
let b = new Person('b')
b.name // b
b.smart = false
b.smart // false
a.smart // false
b.__proto__ === a.__proto__ // true

對 b 的 smart 屬性進行修改,a 訪問 smart 也有原先的 true 變爲 false 了。

😆 Object.prototype

Object.prototype.__proto__ // null

null 是什麼意思?此處無對象的意思,說明 Object.prototype 沒有原型,查到這裏就中止查找了,若是在找不到目標屬性,就返回 undefined。

😎 自身屬性優先

若是自身和原型上存在同名屬性,會優先使用自身屬性,例如:

function Person () {
  this.name = 'Jon'
}
Person.prototype.name = 'people'
let jon = new Person()
jon.name // Jon

🚀 參考

相關文章
相關標籤/搜索