1、作用域
作用域分为:全局作用域、函数作用域、块级作用域
2、自由变量
- 一个变量在当前作用域没有定义,但被使用了
- 向上级作用域,一层一层依次寻找,知道找到为止
- 如果到全局作用域都没找到,则报错 XX is not defined
3、闭包
闭包其实是作用域应用的特殊情况,有两种表现:
- 函数作为参数被传递
- 函数作为返回值被返回
// 函数作为返回值
function create() {
let a = 100
return function() {
console.log(a)
}
}
const fn = create();
const a = 200;
fn() // 100
// 函数作为参数被传递
function print() {
const b = 200;
fn2();
}
const b = 100;
function fn2() {
console.log(b)
}
print() // 100
// 总结:自由变量的查找是在函数定义的地方向上级作用域查找,不是在执行的地方!!
// 闭包的实例
function isFirstLoad() {
var _list = [];
return function (id) {
if (_list.indexOf(id) > -1) {
return false;
} else {
_list.push(id);
return true;
}
}
}
var firstLoad = isFirstLoad();
firstLoad(10); // true
firstLoad(10); // false
firstLoad(20); // true
firstLoad(20); // false
4、this 的使用场景
this 在各个场景取什么值,是在函数执行时确定的,不是在函数定义时确定的。
箭头函数中的 this 取得是上级作用域的 this
- 作为普通函数
- 使用 call、bind、apply
- 作为对象方法被调用
- 在 class 方法中调用
- 箭头函数
// 情景一
function fn1() {
console.log(this)
}
fn1(); // window
// 情景二
fn1.call({ a: 100}); // { a: 100}
// 情景三
const fn2 = fn1.bind({ a: 200 });
fn2() // { a: 200 }
// 情景四
const zhangsan = {
name: '张三',
sayHi() {
// this -> 当前对象
console.log(this)
},
wait() {
setTimeout(function() {
console.log(this) // window
})
}
}
zhangsan.sayHi();
zhangsan.wait();
// 情景五
const lisi = {
name: '李四',
sayHi() {
// this -> 当前对象
console.log(this)
},
wait() {
setTimeout(() => {
// 箭头函数中的 this 取得是上级作用域的 this
console.log(this) // this -> 当前对象
})
}
}
lisi.sayHi();
lisi.wait();
// 情景六
class People {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(this)
}
}
const melody = new People('Melody')
melody.sayHi(); // People {name: "Melody"}
const coco = new People('coco')
coco.sayHi(); // People {name: "coco"}
5、手写 bind 函数
function fn1(a, b) {
console.log('this:', this);
console.log(a, b)
return 'this is fn1';
}
const fn2 = fn1.bind({x: 100}, 10, 20)
fn2(); // this: {x: 100}
// 模拟 bind
Function.prototype.bind1 = function() {
// 将参数拆解为数组
const args = Array.prototype.slice.call(arguments);
// 获取 this(数组第一项)
const t = args.shift();
// fn1.bind(..) 中的 fn1
const self = this
// 返回一个函数
return function() {
return self.apply(t, args);
}
}
const fn3 = fn1.bind1({x: 100}, 10, 20)
fn3(); // this: {x: 100}