在聲明定義函數時,函數都會有一個
prototype
屬性,這個屬性就是一個指針,指向一個對象,而這個對象就是原型對象(簡稱原型)
經過構造函數建立的實例對象,能夠直接訪問到構造函數的
prototype
屬性上(即原型對象)的屬性和方法
對象有__proto__
屬性, 屬性值指向了當前的原型對象, 原型對象也是對象, 原型對象也有__proto__
屬性,原型對象的__proto__
屬性值指向了原型對象的原型對象, 這樣一環套一環,造成的鏈式結構叫作原型鏈
原型鏈特色:面試
__proto__
)等於構造函數的顯示原型(prototype
)f1.__proto__ === Foo.prototype //true
Function
的實例,即函數都是經過new
Function
產生的Foo.__proto__ === Function.prototype //true Date.__proto__ === Function.prototype //true Object.__proto__ === Function.prototype //true
Function
也是new
本身產生的,即Function
的隱式原型等於本身的顯示原型Function.__proto__ === Function.prototype //true
new
Object
產生的,即原型對象的隱式原型指向Object的顯示原型Foo.prototype.__proto__ === Objecct.prototype //true Function.prototype.__proto__ === Objecct.prototype //true
Object
的原型,是原型鏈的盡頭Object.prototype.__proto__ === null //true
constructor
,該屬性指向當前的構造函數Foo.prototype.constructor === Foo //true Object.prototype.constructor === Object //true Function.prototype.constructor === Function //true
注意點:函數
__proto__
屬性prototype
屬性和__proto__
屬性constructor
屬性和__proto__
屬性簡化記憶: 沿着對象的原型鏈往上找this
注意點: 關鍵看對象上是否有該屬性, 而不在意其值是啥spa
簡單記憶: 有就修改, 沒有就添加prototype
function Person(name, age){ // ****有形參, 無實參, 形參是undefined***** this.name = name; this.age = age; } Person.prototype.name = "lw"; Object.prototype.gender = "male"; // 變化的點 var p = new Person(); console.log(p); // p實例對象的原型鏈 // p ==> Person.prototype ==> Object.prototype ==> null; console.log(p.name); // undefined **** console.log(p.age); // undefined **** console.log(p.gender); // male console.log(p.sex); // undefined
function Person(name) { // name ==> undefined if (name) { this.name = name; } } Person.prototype.name = "ls"; Person.prototype.money = 100; var p = new Person(); console.log(p); // p實例對象自身沒有name屬性 console.log(p.name); // ls undefined console.log(p.money); // 100 100
function A() { } A.prototype.n = 1; var b = new A(); A.prototype = { n:2, m:3 } var c = new A(); console.log(b.n, b.m, c.n, c.m) //1 undefined 2 3
function F() {} Object.prototype.a = function () { console.log('a()') } Function.prototype.b = function () { console.log('b()') } var f = new F(); f.a() //a() f.b() //報錯 F.a() //a() F.b() //b()
instanceof
判斷複雜數據的具體類型的原理是什麼?A intanceof B若是B的顯示原型屬性指向的對象在A的原型鏈上,則返回true,不然返回false指針
/* 封裝一個instanceof的具體實現 參數: A: 實例對象 B: 構造函數 返回值:true或者false */ function myInstanceof(A, B) { // 判斷A的數據類型,若是A是簡單數據類型或者null,則直接返回false var styleA = typeof A if((styleA !== 'function' && styleA !== 'object') || styleA === null) { return false } // 判斷B構造函數的顯示原型是否在A實例對象的隱式原型上 var protoA = A.__proto__ while(protoA !== null) { if(protoA === B.prototype) { return true } protoA = protoA.__proto__ } return false }