[深刻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')
复制代码