JS建構函式,原型鏈,原型物件總結

Monster1010發表於2020-01-08

JS建構函式,原型鏈,原型物件總結

建構函式

建構函式第一個字母大寫

使用this指向當前物件的 公有屬性

var Car = function(wheels, seats, engines) {
  this.wheels = wheels;
  this.seats = seats;
  this.engines = engines;
};
var myCar = new Car(6,3,1)
複製程式碼

也可以建立私有屬性私有方法,它們兩個在物件外部是不可訪問的

用var 關鍵詞去建立變數,代替this建立私有屬性;比如,我們想記錄我們的car行駛的 speed ,但是我們希望外面的程式碼對 speed 的修改只能是加速或減速(而不是變成字串、直接賦值成某個速度等其他操作),那麼如何達到這類操作的目的呢?

var Car = function() {
    // this is a private variable
    var speed = 10;
    // these are public methods
    this.accelerate = function(change){
        speed =+ change
    }
    this.decelerate = function() {
    	speed -= 5;
   }
    this.getSpeed = function(){
        return speed
    }
}
複製程式碼

instanceof

判斷某個物件是否為某個建構函式的例項

console.log(myCar instanceof Car)
複製程式碼

靜態成員和例項成員

靜態成員: 寫成物件字面量的形式,直接使用物件來呼叫。

// 一般用於 工具  的寫法,工具中使用靜態成員,即工具中的方法如 max(),PI 只有一個
var MyMath = {
    PI:3.1415,
    max:function(){},
    min:function(){}
}

MyMath.PI
MyMath.max()
複製程式碼

例項成員:建構函式中的成員: p.sayHi()

function Person(name,age) {
    this.name = name,
    this.age = age,
    this.sayHi = function(){}
}
//當有很多例項的時候,使用建構函式來建立
var p = new Person('zs',18)
複製程式碼

建構函式原型

每一個建構函式都有一個屬性 : 原型/原型物件 prototype

function Person(name,age) {
    this.name = name,
    this.age = age,
}
console.dir(Person.prototype)
//那麼就可以為Person的原型物件增加方法,這樣用Person建構函式建立出來的例項都可以訪問新增加的方法
Person.prototype.sayHi = function() {
    console.log("hi")
}

 var p1 = new Person('ls',12)
 var p2 = new Person('tom',13)
 
 p1.sayHi()
 p2.sayHi()
 
 這樣做的優點: 節省記憶體

 p1.sayHi 和  p2.sayHi 是相等的,指向同一個記憶體空間
 如果在Person()內部定義 sayHi 方法的話,新建立的p1,p2會各自在記憶體建立空間
複製程式碼
 物件本身有 __proto__ 屬性,當呼叫物件的屬性或方法時,先去找物件本身的屬性/方法;找不到的話 再去調原型中的屬性/方法
 
 物件的__proto__ 屬性 等於 建構函式的prototype,物件可以訪問原型物件所有成員
 
 p1.__proto__ === Person.prototype
 > true
 
 constructor 記錄了建立該物件的建構函式
 p1.constructor === Person
 > true
複製程式碼

JS建構函式,原型鏈,原型物件總結

注意:constructor 屬性
function Person(){
    
}
var p1 = new Person()
console.log(p1.constructor === Person.prototype.constructor)
>true

原因:
當獲取 person.constructor 時,其實 person 中並沒有 constructor 屬性,當不能讀取到constructor 屬性時,會沿著原型鏈從 person 的原型也就是 Person.prototype 中讀取,正好原型中有該屬性,所以:

person.constructor === Person.prototype.constructor
複製程式碼

原型鏈

同理如圖:

查詢物件是否具有某個方法或屬性時,會由底向上查詢:當底層物件沒有時,會在其原型物件上找,其原型物件沒用時,會再其原型物件的原型物件上找;

JS建構函式,原型鏈,原型物件總結

使用原型物件注意點

  1. 當我們改變建構函式的prototype的時候,需要重新設定constructor屬性
//在Person.prototype.sayHi = function(){} 基礎上進一步改進
Person.prototype = {
    constructor:Person,     //注意點
    sayHi:function(){
        console.log("hi")
    }
}

var p1 = new Person('zs',18)
p1.sayHi()
複製程式碼
  1. 先設定原型屬性,再建立物件,才能訪問原型物件的成員

原型物件的應用

擴充內建物件的功能,比如給array方法 增加一個求偶數的和的功能

var arr = [1,2,4,5]
Array.prototype.getSum = function(){
    var sum = 0;
    for (var i = 0;i < this.length; i++){
        if(this[i] %2 === 0) {
            sum += this[i]
        }
    }
    return sum
}
複製程式碼
//但是能不能用下面這種方法呢?
Array.prototype = {
    getSum = function(){}
}
//答案是不能!因為Array,String 都屬於內建物件,如果用以上方法,會覆蓋掉他們本身的那些方法
複製程式碼

相關文章