系列文章:算法
在 JavaScript 中,共有6種類型主要類型:數組
對象的內容是由一些存儲在特定命名位置(任意類型的)值組成的,咱們稱之爲屬性。瀏覽器
⚠️注意:即便在對象的文字形式中聲明一個函數表達式,這個函數都不會「屬於」一個對象,他們只是對於相同函數的多個引用。bash
從 ES5 開始,全部的屬性都具有屬性描述符:閉包
writable:是否能夠修改屬性的值。值爲false時,至關於定義了一個空操做setter。函數
configurable:若是屬性是可配置的,就可使用 defineProperty(...) 進行修改屬性描述符。configurable的值設置爲false是單向操做,沒法撤銷!post
⚠️注意:即便 configurable:false,仍是能夠把 writable 的值從 true 改爲 false,但不能夠由 false 改爲 true。測試
enumerable:控制的是屬性是否會出如今對象的屬性枚舉中。ui
⚠️注意:屬性不必定包含值——也多是包含getter/setter的「訪問描述符」this
屬性訪問時,對象默認的內置 [[Get]] 操做首先在對象中查找是否有名稱相同的屬性,遍歷可能存在的[[prototype]]鏈,若是不管如何也沒找到名稱相同的屬性,則返回值 undefined。
⚠️注意:訪問變量時,沒找到會拋出一個 ReferenceError 異常。剛問對象屬性時,沒找到會返回 undefined。
當給屬性賦值:
JavaScript 中的對象有一個特殊的 [[prototype]] 內置屬性,是對其餘對象的引用。全部普通的 [[prototype]] 最終都會指向內置的 Object.prototype。
全部的函數默認都會擁有一個名爲 prototype 的公有且不可枚舉的屬性,它會指向另外一個對象,這個對象被稱爲原型,這個對象默認有一個公有且不可枚舉的屬性.constructor,這個屬性引用的是對象關聯的函數。
[[prototype]]機制就是指對象中的一個內部連接引用另外一個對象。
JavaScript 會在兩個對象之間建立一個關聯,這樣一個對象就能夠經過委託來訪問另外一個對象的屬性和函數。
var bar = Object.create(foo);
會建立一個對象 bar 並把它關聯到 foo。
調用 Object.create(...)會憑空建立一個「新」對象,並把新對象內部的[[prototype]] 關聯到指定的對象...,這樣會直接把原始的關聯對象拋棄掉。
有如下幾種方法檢查兩個對象之間的關係:
⚠️注意:絕大多數(不是全部)的瀏覽器支持__proto__ 這個非標準的方法訪問內部的[[prototype]],__proto__存在於內置 Object.prototype 中,看起來像個屬性,其實更像一個 getter/setter。
練習題1:
function Test() {
Test.prototype.add = num => {
this.number = num
}
Test.prototype.number = 0
}
t1 = new Test()
t2 = new Test()
t1.add(12)
var a = t1.number
var b = t2.number
console.log(a, b) // => 0,12
複製代碼
每實例化一次Test,Test.prototype.add都會被從新賦值一次,而且賦值的函數爲箭頭函數,箭頭函數無自身的上下文,其中的this指向Test上下文中的this,即每次實例化的實例對象。因此,t2 實例化後 Test.prototype.add 裏的 this 指向t2,t1 調用 add 函數時,給 t2 的number 賦值。
練習題2:
var A = function() {};
A.prototype.n = 1;
var b = new A();
A.prototype = {
n: 2,
m: 3
}
var c = new A();
console.log(b.n); // 1
console.log(b.m); // undefined
console.log(c.n); // 2
console.log(c.m); // 3
複製代碼
⚠️注意:JavaScript 中的引用和其餘語言中的引用/指針不一樣,不能指向別的變量或者引用,只能指向值。
b 在實例化過程當中,b.__proto__ = A.prototype
,此時 A.prototype = {n: 1}
,當 A.prototype = { n: 2, m: 3 }
時,打破原型鏈,A.prototype 引用了新內存地址的對象,b.__proto__
指向的依舊是舊內存地址的對象。若是是 A.prototype.n = 2; A.prototype.m = 3;
就不會指向新的引用。
練習題3:
var F = function() {};
Object.prototype.a = function() {
console.log('a');
};
Function.prototype.b = function() {
console.log('b');
}
var f = new F();
f.a(); // a
f.b(); // TypeError: f.b is not a function
F.a(); // a
F.b(); // b
複製代碼
f的原型鏈:f => f.__proto__ => F.prototype => F.prototype.__proto__ => Object.prototype => Object.prototype.__proto__ => null
F的原型鏈:F => F.__proto__ => Function.prototype => Function.prototype.__proto__ => Object.prototype => Object.prototype.__proto__ => null
練習題4:
function Person(name) {
this.name = name
}
let p = new Person('Tom');
question1: p.__proto__等於什麼? // p.__proto__ === Person.prototype
question2: Person.__proto__等於什麼? // Person.__proto__ === Function.prototype
複製代碼
以爲有收穫的,點個贊再走吧~