天天看點

三分鐘帶你了解JS原型

一. 理論基礎

1. 普通對象和函數對象

JavaScript中,萬物皆對象!但是對象也是有差別的,分為普通對象和函數對象。

function F(){}; //F:普通對象
var f = new Function(); //f: 函數對象
var o = new Object(); //o: 函數對象
           

Object、Function是js自帶的函數對象。

2. 構造函數

與大部分面向對象的語言不同,JavaScript中并沒有引入類(class)的概念,但JavaScript仍然大量使用了對象,為了保證對象之間的聯系,JavaScript引入了原型與原型鍊的概念。

與Java不同,JavaScript的new操作符後面跟的并非類名而是函數名,JavaScript并非通過類而是直接通過構造函數來建立執行個體。

function Dog(name, color) {
    this.name = name
    this.color = color
    this.bark = () => {
        console.log('wangwang~')
    }
}

const dog1 = new Dog('dog1', 'black')
const dog2 = new Dog('dog2', 'white')

           

上述代碼中,有兩個執行個體被建立,它們有自己的屬性,但bark方法是一樣的,而通過構造函數建立執行個體的時候,每個執行個體都需要建立這個方法。為什麼不把這個方法放到一個單獨的位置,并讓所有執行個體都可以通路到呢?

3. 構造函數和普通函數

構造函數和普通函數主要有以下差別:

  • 調用方式:

    (1)構造函數需要使用new運算符調用,如果沒有參數,可以省略括号,比如new Object

    (2)普通函數的調用不需要new運算符,而且必須有括号

  • this指向

    (1)構造函數的this會指向建立的對象執行個體上

    (2)普通函數的this則指向函數的調用者

  • 命名方式

    (1)構造函數名稱首字母要大寫

    (2)普通函數首字母要小寫,使用駝峰命名方式

這裡就需要用到原型。

二. 原型

  • 每一個構造函數都有一個prototype屬性,指向原型對象。當使用這個構造函數建立執行個體的時候,prototype屬性指向的原型對象,就是執行個體的原型對象。
  • 原型對象預設擁有一個constructor屬性,指向指向它的那個構造函數。
  • 每個對象都有一個隐藏屬性

    obj._proto_

    ,每個函數對象都有一個

    function.prototype

    ,它們指向同一原型對象。
  • 原型對象就是用來存放執行個體中共有的屬性。
  • 通路對象屬性時,會先在對象自身屬性内查找,若沒有找到,則會跳轉到對象的原型對象中查找。

那麼上述代碼就可以修改為

function Dog(name, color) {
    this.name = name
    this.color = color
}

Dog.prototype.bark = () => {
    console.log('wangwang~')
}
           

接着就可以建立執行個體,并通路它的bark方法:

const dog1 = new Dog('dog1', 'black')
dog1.bark()  //'wangwang~'
           

這個時候,我們還可以重寫bark方法:

const dog2 = new Dog('dog2', 'white')
dog2.bark = () => {
    console.log('miaomiaomiao???')
}
dog1.bark()  //'wangwang~'
dog2.bark()  //'miaomiaomiao???'
           

由上可知,重寫的bark方法是為自己添加了一個新的方法使原型中的bark方法被覆寫了,而并非直接修改原型中的方法。

要修改原型中的方法應該這樣:

Dog.prototype.bark = () => {
    console.log('haha~')
}
dog1.bark()  //'haha~'
dog2.bark()  //'haha~'
           

三. 結語

如有遺漏,後面會繼續總結。

參考

https://www.jianshu.com/p/dee9f8b14771

https://juejin.im/post/5a94c0de5188257a8929d837

https://www.cnblogs.com/shayueblog/p/5813230.html

http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html