作用域,闭包
es6 之前,js 只有全局作用域和函数作用域
|
|
这段代码有两个阶段,创建和执行。创建即创建执行上下文,包括变量对象,this,arguments。执行即 js 执行
执行和创建不是完全分开的,执行的时候也会创建。
- 创建阶段(变量提升,函数提升)
- 变量对象
- foo: undefiend
- func2: undefined
- arguments: {length: 0}
this: window
1 2 3 4 5 6 7 8 9 10 11 12 13var foo = undefined; var func2 = undefined; console.log(foo); function func() { var bar = 1; return function() { console.log(bar++); }; } foo = 123; func2 = func(); func2(); func2();
- 执行阶段
(1) 执行
|
|
(2) 又创建了
可以看出是一个栈的结构,因此也可以执行上下文栈
- 变量对象
- bar: undefined
- arguments: {length: 0}
- this: window
(3) 继续执行
|
|
这时返回一个函数,形成了闭包。(闭包可以理解为,把上一层的执行执行上下文保存一下,不会在函数执行结束后就销毁)
(4) 继续执行
|
|
作用域链,函数作用域查找一个变量没有定义,会向上查找,一直到全局作用域都没找到就会报错 x is not defined
原型和原型链,继承
定义一个构造器
|
|
创建实例
|
|
原型或原型对象(可以理解为就是构造器的一个属性,指向一个对象)
|
|
原型上的方法可以理解为公共方法(可以节省空间,不用每个实例都创建一个 say 方法)。
|
|
当访问 say 方法时,先在实例上找,没找到就去原型对象上找,还没找到,就去原型对象的原型对象上找…这就是原型链
等等,原型对象的原型对象是什么?这就说到继承了
声明一个 Worker 构造器
|
|
worker 也是 person,所以要继承 Person 类
1.原型链继承(基础版)
|
|
缺点:
- 不能传参数(我直接设置的 w1.name)
- 子类实例共享了父类的引用属性
2.借用构造函数
构造函数修改 this 指向
|
|
缺点:没有继承父类原型上的方法
3.组合继承
|
|
缺点:父类和子类的原型指向了同一个原型对象
4.寄生组合继承
使用 Object.create(),创建一个对象,它的原型是 Person.prototype
|
|