作用域
根据名称查找变量的规则。
词法作用域
定义在词法阶段的作用域,也就是写代码的时候,把变量命名在哪决定的。
函数作用域
函数花括号内部的全部变量,在函数内部使用。
闭包
函数嵌套函数,内层函数引用了外层函数作用域下的变量,并且内层函数在全局作用域下可以访问,就形成了闭包。这是一种现象。
- 应用场景:闭包是用来保存执行环境的。
this的指向
this的指向,是根据上下文动态决定的,他永远返回一个对象或者undefined
- 在简单调用时,this 默认指向的是window / global / undefined / (浏览器/node/严格模式)
- 对象调用时,绑定在对象上
- 使用call,apply,bind时,绑定在指定的参数上
- 在使用new关键词的时候,绑定到新创建的对象上(以上三条优先级:new > apply/call/bind > 对象调用)
- 使用箭头函数,根据外层规则决定
箭头函数不可以作为构造函数
js
function test() {
return this
}
console.log(test.call(4)) // [Number: 4] 包装对象
js
const foo = {
bar: 10,
fn: function () {
console.log(this)
console.log(this.bar)
}
}
var fn1 = foo.fn;
fn1(); // global undefined
foo.fn(); // foo 10
js
const person = {
name: "luyi",
brother: {
name: 'yunyin',
fn: function () {
return this.name
},
fn2: () => {
return this.name
}
}
}
console.log(person.brother.fn()); // yunyin
console.log(person.brother.fn2()); //undefined
js
const o1 = {
text: 'o1',
fn: function () {
return this.text
}
}
const o2 = {
text: 'o2',
fn: function () {
return o1.fn()
}
}
const o3 = {
text: 'o3',
fn: function () {
var fn = o1.fn
return fn() // 这里的this指向了全局
}
}
console.log(o1.fn()) // o1
console.log(o2.fn()) // o1
console.log(o3.fn()) // undefined 说明只看方法前面是谁调用的
js
window.id = 'window';
document.getElementById('div1').onclick = function () {
console.log(this.id); // div1
const callback = function () {
console.log(this.id); //因为是普通函数调用,所以this 指向 window
}
callback();
}
js
var obj = {
name: "jone",
arr: [1, 2, 3],
print() {
this.arr.forEach(function (v) {
console.log(this.name);
})
}
}
obj.print(); // undefined undefined undefined
js
var number = 5; // 10 20
var obj = {
number: 3, // 6
fn1: (function () {
var number; // 3 9 27
this.number *= 2;
number = number * 2;
number = 3;
return function () {
var num = this.number;
this.number *= 2;
console.log(num);
number *= 3;
console.log(number);
}
})()
}
var fn1 = obj.fn1;
fn1.call(null);
obj.fn1();
console.log(window.number);
// 10 9 3 27 20
call、apply、bind
都可以修改this指向,只不过bind绑定以后返回新的方法不执行,而apply传递数组
call与bind联用
js
// call 方法来源于Function.prototype
// 这里相当于改写了 slice 方法
var slice = Function.prototype.call.bind(Array.prototype.slice)
console.log(slice([1, 2, 3], 0, 1)); // [1]
上文中,.bind(Array.prototype.slice)
将Array.prototype.slice
永久绑定给了这里的call
作为this传入。
如果不理解看看这个:console.log(Array.prototype.slice.call([1, 2, 3], 0, 1))
还不理解再看看这个:console.log([1, 2, 3].slice(0, 1))