prototype

1. 構造函數:

構造函數就是普通函數,爲了和其餘函數區別,第一個字母大寫。
特色:node

1.內部使用this表示 實例對象。
2. 生成對象用new關鍵字

2. 構造函數,原型對象和實例對象的關係

const Anim = function (name) {
  this.name = name;
}

const cat = new Anim('cat');

內存圖:瀏覽器

clipboard.png

log驗證:函數

console.log(cat.__proto__);// Anim{}
console.log(Anim.prototype);//Anim{}
console.log(Anim.prototype === cat.__proto__);// true

在node環境中Anim.prototype輸出的是Anim{},而在瀏覽器環境輸出的更明白一些
截圖測試

clipboard.png

node環境仍是有些問題的,建議不要在node環境測試。this

3. 其餘log

console.log(cat.__proto__);// Anim的prototype,含constructor的對象
console.log(cat.__proto__.__proto__);//Object的prototype,含constructor
console.log(cat.__proto__.__proto__.__proto__);//null

console.log(cat.__proto__);// Anim的prototype,含constructor的對象
console.log(cat.__proto__.__proto__);//Object的prototype,含constructor
console.log(cat.__proto__.__proto__.__proto__);//null

console.log(Anim.__proto__);// Function的prototype,一個含constructor的對象
console.log(Anim.__proto__.__proto__);// Object的prototype,含constructor的對象
console.log(Anim.__proto__.__proto__.__proto__);// null

4. Object.getPrototypeOf()

Object.getPrototypeOf(obj) 獲取對象obj的原型對象 至關於obj.__proto__,只是__開頭的是內部屬性,不建議使用,推薦使用Object.getPrototypeOf()spa

console.log(cat.__proto__);// Anim{}
console.log(Object.getPrototypeOf(cat));// Anim{}
console.log(Anim.__proto__);
console.log(Object.getPrototypeOf(Anim));// [Function]

5. constructor

原型對象prototype對象有一個constructor屬性,指向構造函數對象,而構造函數對象有個prototype屬性指向原型對象。prototype

console.log(Anim.prototype.constructor === Anim);// true

由於constructor在原型對象上,因此全部的實例對象都有constructor屬性,並且都等於Anim.cat自己沒有constructor屬性,constructor是其原型鏈上的屬性。code

console.log(cat.constructor === Anim.prototype.constructor);// true
console.log(cat.constructor === Anim);// true

constructor的做用1:判斷實例對象屬於哪一個構造函數

function Cat(){}

function Dog(){}

function isDog(obj){
  return obj.constructor === Dog;
}

const black = new Cat();
const white = new Dog();
console.log(isDog(black));// false
console.log(isDog(white));// true

constructor的做用2:實例對象能夠調用構造函數

const yellow = new white.constructor();
console.log(isDog(yellow));// true

constructor和prototype都是關聯原型對象和構造函數的紐帶,兩者不可只改其一,必須同時修改。

6. instanceof

console.log(yellow instanceof Dog);

左側是實例對象,右側是構造函數。可能會想到原理是對象

yellow.constructor === Dog

除了使用constructor,還有Object.prototype.isPrototypeOf(),對象實例的isPrototypeOf方法,用來判斷一個對象是不是另外一個對象的原型ip

const date = new Date();

console.log(date instanceof Date);// true
console.log(date instanceof Object);// true

console.log(Date.prototype.isPrototypeOf(date));// true
console.log(Object.prototype.isPrototypeOf(date));// true

instanceof對整個原型鏈上的對象都有效,所以同一個實例對象,可能會對多個構造函數都返回true。

7. Object.create

const a = {
  name:'aaaa',
  log:function(){
    console.log(this.name);
  }
};

const b = Object.create(a);
b.name = 'bbb';
const c = Object.create(b);
c.name = 'ccc';

打印a,b,c

clipboard.png

clipboard.png

clipboard.png

console.log(a.__proto__ === Object.prototype);// true
console.log(b.__proto__ === a);// true
console.log(c.__proto__ === b);// true

猜想create的過程

b.__proto__ = a;

若是建一條原型鏈,可使用create,只是沒有構造函數,也不存在prototype。

字面量對象沒有prototype屬性,沒法使用new關鍵字建立實例對象。

var o = {
    name:'michael',
    age:10,
    say:()=>{
        console.log('hello');
    }
};