JS中this问题
先看一段代码
在这段代码中,定义一个普通函数,并在函数中打印this
然后以不同的方式调用,打印出不同的结果
function fn() {
console.log(this);
}
// 直接调用
fn();
let obj = {
name: 'zzk'
};
// call调用
fn.call(obj)
let obj2 = {
name: 'sss',
func: fn
}
obj2.func()
打印结果
得出的结论时this只有在函数调用时才能决定this是谁
this的绑定规则分为
- 默认绑定
- 隐式绑定
- 显示绑定
- new绑定
1.默认绑定
独立函数调用既默认绑定,没有绑定到某个对象上的调用函数
// --------------- 独立的函数调用
function fn() {
console.log(this);
}
// 独立的函数调用
// 函数内部的this,在浏览器中表示window
fn(); // window
打印结果:
2.隐式绑定
通过某一个对象进行调用
function fn() {
console.log(this);
}
var obj = {
name: "zzk",
fn: fn,
}
obj.fn(); // 打印出对象obj
打印结果:
隐式绑定回把obj对象绑定到this上
// --------------- 隐式绑定
var obj = {
name: "wc",
fn: function() {
console.log(this);
}
}
var obj2 = {
name: "xq",
gn: obj.fn
}
// fn中this是谁,看.前面是谁
obj2.gn(); // obj2
3.显示绑定
通过call,apply,bind可以改变this的指向
function fn() {
console.log(this);
}
let obj = {
name: "zzk",
}
fn.call(obj) // obj
fn.apply(obj) // obj
let newFn = fn.bind(obj)
newFn(); // obj
如果call,bind后面跟的是基本数据类型
function fn() {
console.log("fn...");
console.log(this);
}
fn.call("hello"); // 会把"hello"包装成一个新的对象
fn.call(undefined); // 参数是und this指定window
fn.call(null); // 参数是null this指定window
4.new绑定
使用new关键字,创建一个新的对象,会执行如下步骤
- 创建一个新对象
- 这个空对象prototype会指向构造函数的原型,
- 新对象会绑定到函数调用的this上
- 如果函数没有返回其他对象,则表达式会返回这个新对象
5.箭头函数绑定
箭头函数的this会指向上层作用域
console.log(this); // 最外层的this是window
var fn = () => {
// 箭头函数中的this都需要向外找一级
console.log(this);
}
fn(); // window
var obj = {
name: "wc"
}
fn.call(obj); // window
示例中始终指向window