[深刻01] 執行上下文
[深刻02] 原型鏈
[深刻03] 繼承
[深刻04] 事件循環
[深刻05] 柯里化 偏函數 函數記憶
[深刻06] 隱式轉換 和 運算符
[深刻07] 瀏覽器緩存機制(http緩存機制)
[深刻08] 前端安全
[深刻09] 深淺拷貝
[深刻10] Debounce Throttle
[深刻11] 前端路由
[深刻12] 前端模塊化
[深刻13] 觀察者模式 發佈訂閱模式 雙向數據綁定
[深刻14] canvas
[深刻15] webSocket
[深刻16] webpack
[深刻17] http 和 https
[深刻18] CSS-interview
[react] Hooks前端
[部署01] Nginx
[部署02] Docker 部署vue項目
[部署03] gitlab-CIvue
[源碼-webpack01-前置知識] AST抽象語法樹
[源碼-webpack02-前置知識] Tapable
[源碼-webpack03] 手寫webpack - compiler簡單編譯流程java
即全部對象都繼承了 Object.prototype 對象上的屬性和方法,這就是全部對象都具備valueOf和toString的緣由
Object.prototype的原型是null,null沒有任何屬性和方法,也沒有本身的原型,原型鏈終止
null是爲了防止死鏈
讀取對對象的屬性時,自身沒有會到原型上找,原型沒有會到原型的原型上找,直到Object.prototype,仍是沒有返回undefined
function A(){} //---------------------- 定義構造函數A
A.prototype = new Array() // ---------- 將A.prototype指向實例數組,那麼A的實例就能繼承數組原型鏈上的屬性和方法
A.prototype.constructor = A // -------- 修改prototype的同時,也要修改constructor防止意外
const a = new A()
a.push(1)
a instanceof Array // true
複製代碼
由於constructor屬性在prototype對象上,因此constructor屬性被全部實例繼承
<script>
function A(){}
const a = new A()
console.log(A.prototype.constructor === A) // true
console.log(a.constructor === A.prototype.constructor) // true,constructor屬性在prototype對象上,因此能被實例繼承並訪問
console.log(a.constructor === A) // true,constructor的做用是能夠肯定實例由哪一個構造函數產生
console.log(a.constructor === RegExp) // false
console.log(a.hasOwnProperty('constructor'), "a.hasOwnProperty('constructor')") // constructor不是實例自身屬性,繼承的
console.log(new a.constructor(), 'constructor的另外一個做用: 一個實例能夠藉助constructor新建另外一個實例')
const b = new a.constructor()
console.log( b instanceof A) // true , 即b是A的其中一個實例
</script>
複製代碼
constructor
constructor表示原型對象和構造函數之間的關聯關係,修改prototype,須要同時修改constructor,防止引用出錯
<script>
function A () {
console.log('A構造函數')
}
console.log(A.prototype, '修改以前的A.prototype')
console.log(A.prototype.constructor, '修改以前的A.prototype.constructor') // A
console.log(A.prototype.constructor.name, '修改以前的A.prototype.constructor.name => 修改前的constrctor名稱')
A.prototype = {name: 'woow_wu7'}
console.log(A.prototype.constructor, '修改以後的A.prototype.constructor') // Object
console.log(A.prototype.constructor.name, '修改以後的A.prototype.constructor.name => 修改後的constrctor名稱')
A.prototype.constructor = A
console.log(A.prototype.constructor, '修改prototype後,要從新指定A.prototype.constructor=A,防止引用出錯')
</script>
複製代碼
instanceof
function A(){}
const a = new A()
console.log(a instanceof A, 'instanceof的原理是檢查右邊構造函數的原型對象是否在左邊對象的原型鏈上')
console.log(A.prototype.isPrototypeOf(a), 'instanceof等價於這樣')
var d = new Date();
d instanceof Date
// true
// d既是Date的實例,也是Object的實例
d instanceof Object
// true
// 由於instanceof檢查的是右邊構造函數的實例,是否在左邊實例對象的原型鏈上,檢查整個原型鏈
// 因此同一個實例,可能對多個構造函數返回ture
var obj = Object.create(null); // 以null爲原型對象建立實例
typeof obj // "object"
Object.create(null) instanceof Object // false
複製代碼
installof能夠解決調用構造函數時,忘記加new命令的狀況
function A() {
if(!(this instanceof A)) { // 若是this不是A的實例,說明不是new命令調用的,那麼執行new
return new A()
}
else {
this.name = 'woow_wu7'
}
}
const a = new A()
console.log(a)
複製代碼
Object.getPrototypeOf
- 獲取參數對象的原型對象,是獲取原型對象的標準方法
Object.getPrototypeOf(Object.prototype) === null // true
Object.getPrototypeOf(Function.prototype) === Object.prototype // true
Object.getPrototypeOf({}) === Object.prototype // true
複製代碼
Object.setPrototypeOf(現有對象,原型對象)
const a = {}
const b = {name: 'woow_wu7'}
const res = Object.setPrototypeOf(a, b) // 將b設置成a的原型,注意返回值是a
Object.getPrototypeOf(a) === b // true
console.log(a.name)
console.log(res) // a, 返回值是a
複製代碼
var F = function () {
this.foo = 'bar';
};
var f = new F();
// 等同於
var f = Object.setPrototypeOf({}, F.prototype);
// 返回值f是第一個參數 {}
// Object.setPrototypeOf({}, F.prototype) => 至關於 {}.__proto__ = F.prototype
F.call(f);
複製代碼
(構造函數其實就是普通的函數,只是用new命令調用時,this指向了實例,而且首字母大寫來區分,不大寫也行,但約定俗成)
有時候只能拿到一個對象,要生成實例對象。Object.create,該實例徹底繼承原型對象的屬性和方法
手動實現一個 Object.create
Object._create = function(obj) {
function F(){}
F.prototype = obj // 新建一個構造函數,將構造函數的prototype指向傳入的對象,執行構造函數,即實例的原型指向了傳入的對象
return new F()
}
複製代碼
Object.prototype.__proto__
__proto__
,其餘環境中沒有__proto__
屬性__proto__
Object.getPrototypeOf讀取原型
,Object.setPrototypeOf(現有對象,原型對象)來設置原型
- `obj.__proto__` // 只有瀏覽器纔有,不建議使用
- obj.constructor.prototype // 手動修改原型時,可能會失真
- Object.getPrototypeOf() // 推薦的獲取方法
複製代碼
直接修改原型對象時,須要同時修改constructor防止失真
function A(){}
const a = new A()
function B() {}
B.prototype = a
const b = new B()
b.constructor.prototype === a // false
// 由於:b.constructor === a.constructor === A.prototype.constructor === A
// 因此:b.constructor.prototype === A.prototype
// 結論:當直接修改prototype屬性時,必定要修改constructor屬性 !!!!!!!!!!!!!!!!!!(重要)
// 若是是下面這樣則:
function A(){}
const a = new A()
function B() {}
B.prototype = a
B.prototype.constructor = B // 修改了prototype,同時修改constructor則引用不會出錯
const b = new B()
b.constructor.prototype === a // true
複製代碼
Date.hasOwnProperty('length') // true
Date.hasOwnProperty('toString') // false
複製代碼
例子:
function X(){}
X.prototype.name = 'woow_wu7';
let x = new X()
'name' in X // true
// 由於:in 運算符返回一個布爾值,表示屬性是否在對象中存在,不區分自身仍是繼承
// 因此:'name' in X => 返回 true
複製代碼
for in
- 用於數組,i表示:key
- 用於對象,i表示:key
- 用於對象時,for...in會遍歷自身屬性和繼承的屬性,
for of
- 用於數組:i表示 value
const objP = {sex: 'man'}
const obj = {name: 'woow_wu7', age: 20, address: 'hangzhou'};
Object.setPrototypeOf(obj, objP)
for(let i in obj) {
console.log(i, 'for in 循環 => 用於對象,會遍歷自身和繼承的屬性') // name,age,address,sex
if (obj.hasOwnProperty(i)) {
console.log(i, '若是隻但願遍歷自身屬性,能夠用Object.prototype.hanOwnProperty(屬性名)來過濾')// name,age,address
}
}
複製代碼
- constructor
- constructor表示構造函數和原型對象之間的關聯關係,若是修改了原型對象,須要一塊兒修改構造函數,防止引用出錯。
-(每個構造函數都有一個prototype屬性,prototype的constructor指向prototype所在的構造函數)
- instanceof
- 原理:instanceof是檢查(右邊構造函數的prototype屬性)是否在(左邊對象)的原型鏈上
- instanceof失效的狀況:
- 若是一個對象的__proto__屬性指向null,則instanceof就會失效
- 由於右邊是構造函數的prototype => 終點是Object.prototype,是否在左邊對象的原型鏈上
- Object.prototype.__prototo__ === null
- Object.prototype instanceof Ojbect // false
// Object.create(null) instanceof Object // false,由於建立的實例沒有任何屬性和方法,也沒有原型
複製代碼