[深刻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] Hooksjavascript
[部署01] Nginx
[部署02] Docker 部署vue項目
[部署03] gitlab-CI前端
[源碼-webpack01-前置知識] AST抽象語法樹
[源碼-webpack02-前置知識] Tapable
[源碼-webpack03] 手寫webpack - compiler簡單編譯流程vue
執行上下文是:javaScript代碼解析和執行時所在的環境,javascript中運行的全部代碼都在執行上下文中執行java
execution:執行
lexical:詞彙的
執行上下文分爲三種類型:node
建立階段:(預編譯階段)react
執行階段:webpack
變量對象VO ,活動對象AO git
(1) 函數執行上下文的,進入函數執行上下文階段(預編譯階段)代碼還未真正執行,此時AO被建立,此時包含的屬性有: |
函數執行上下文
- 建立階段(進入執行上下文階段,或者說預編譯階段),即進入函數執行上下文時,AO被建立,代碼並未真正執行
- 此時AO中的屬性有:arguments, 形參,函數聲明,變量聲明,this
- 代碼示例:
function a(name, age) {
var b = 1
function c() {}
var d = function()()
(function e () {}); // 注意e函數的寫法
var f = function g(){}
}
a('woow') // 注意這裏沒有傳實參age
------------
預編譯階段的AO以下:
AO(a function execution context) = {
arguments: {
......
},
name: 'woow',
age: undefined,
b: undefined,
c: reference to function c(){},
d: undefined
f: undefined
}
// 注意:
// e函數表達式不在AO中
// g函數不在AO中
------------
執行階段的AO以下:
AO(a function execution context) = {
arguments: {
......
},
name: 'woow',
age: undefined,
b: 1,
c: reference to function c(){},
d: reference to FunctionExpression "d",
f: reference to FunctionExpression "f"
}
複製代碼
是規範或引擎實現層面的,在js的環境中沒法訪問,在進入函數執行上下文階段(預編譯階段),VO才被激活,成爲AO
只有成爲了活動對象,變量對象的屬性和方法才能被訪問
優先級: 函數形參 > 函數聲明 > 變量聲明 |
函數名已經存在,則新的覆蓋舊的 |
變量名已經存在,直接跳過變量聲明 |
變量提高
- 優先級:形參 > 函數聲明 > 變量聲明
- 函數名已經存在,則新的覆蓋舊的
- 變量名已經存在,則跳過變量聲明(注意:只是跳過變量的聲明,賦值是正常的賦值)
複製代碼
(例1)
function a(name, age) {
console.log(name) // -------------------------- 'wang'
console.log(age) // --------------------------- undefined
var name = 'woow_wu7'
console.log(name) // -------------------------- 'woow_wu7'
}
a('wang')
實際執行的代碼以下:
function a(name, age) {
var name = 'wang'
var age = undefined // ------------------------ 優先級:形參 > 變量聲明,因此形參聲明並被賦值
// var name = undefined // -------------------- 變量名已經存在了,跳過變量聲明,即這行代碼不執行
console.log(name) // -------------------------- 'wang'
console.log(age) // --------------------------- undefined, 未傳入實參
name = 'woow_wu7' // -------------------------- 執行階段被從新賦值
console.log(name) // -------------------------- 'woow_wu7'
}
a('wang')
複製代碼
(例2)
function a(name, age) {
console.log(name) // -------------------------- function name(){....}
console.log(age) // --------------------------- undefined
var name = 'woow_wu7'
function name() {
console.log('name()')
}
console.log(name) // --------------------------- 'woow_wu7'
}
a('wang')
實際執行的代碼以下:
function a(name, age) {
var name = 'wang' // -------------------------- 優先級:形參 > 函數聲明 > 變量聲明
function name() {...} // ---------------------- 優先級:函數聲明 > 變量聲明;函數名name已經存在,則新的覆蓋舊的
// var name = undefined // -------------------- 變量名已經存在,則跳過變量聲明,至關於該行不執行
console.log(name) // -------------------------- function name(){....}
console.log(age) // --------------------------- undefined
name = 'woow_wu7' // -------------------------- 執行時從新被賦值
function name() {
console.log('name()')
}
console.log(name) // --------------------------- 'woow_wu7'
}
a('wang')
複製代碼
個人語雀:www.yuque.com/woowwu/msyq… juejin.im/post/5dc7db…
juejin.im/post/5bdfd3…
juejin.im/post/5ab072…
juejin.im/post/58ec3c…
www.jianshu.com/p/330b1505e…web
複習canvas
手寫new
- new命令執行構造函數,返回實例對象
- 構造函數中有return,若是後面跟一個對象new命令會返回這個對象,若是後面不是對象,就會返回this對象
- new命令生成的實例對象能夠繼承構造函數的prototype屬性 => 即實例能夠訪問構造函數的prototype上的屬性和方法
- new命令生成的實例能夠訪問構造函數中的屬性和函數
過程:
1. 新建一個空對象
2. 將空對象的隱式原型指向構造函數的顯示原型 => 空對象就能訪問構造函數的prototype上的屬性和方法
3. 將構造函數中的this指向這個空對象 => this上綁定的屬性和方法實際上就綁在了空對象上
4. 執行構造函數 => 若是有return,並返回一個對象,就返回這個對象,若是不是對象,就返回這個空對象
5. 若是構造函數的返回值是一個對象,就返回這個對象。不然返回這個空對象即this對象
代碼:
function Constructor(name) {
this.name = name
this.age = 20
return this
}
Constructor.prototype.address = 'chongqing'
function _new() {
const obj = {}
// 還能夠經過 const obj = new Object()來生成
const paramsConstructor = Array.prototype.shift.call(arguments)
// 獲取傳入new函數的構造函數
// 等於 [].prototype.shift.call(arguments)
// 等於 [].prototype.shifig.apply(arguments)
obj.__proto__ = paramsConstructor.prototype
// 將空對象的隱式原型指向構造函數的顯示原型
// 這樣paramsConstructor.prototype就成了obj的原型對象,obj能夠訪問原型對象上的屬性和方法
// 注意:Object.create() 該方法能夠以參數對象爲原型,返回一個實例對象
// 因此:空對象的生成,加空對象的隱式原型的綁定能夠一行代碼搞定:
//!!!!!!!能夠:const obj = Object.create(paramsConstructor.prototype)
//!!!! 還能夠:const obj = Object.setPrototypeOf({}, paramsConstructor.prototype)
const res = paramsConstructor.apply(obj, arguments)
// 將構造函數中的this綁定在空對象上,並執行構造函數
// 注意:這裏arguments是shift後剩下的值,由於apply能夠本身轉化類數組的對象,因此無需額外操做
return Object.prototype.toString.call(res).includes('Object') ? res : obj
// 若是構造函數返回的是一個對象,就返回這個對象,不然返回這個空對象
// 等於 typeof res === 'object' ? res : obj
}
const res = _new(Constructor, 'woow_wu7')
console.log(res, 'res11')
複製代碼