目录
一、this绑定规则
- 默认绑定:非严格模式下this指向全局对象,严格模式下。独立调用的函数中的this指向的就是undefined
- 隐式绑定:当函数引用有上下文对象时,如 obj.foo() 的调用方式,foo 内的this指向 obj (采取就近原则)
- 显式绑定:通过 call() 或者 apply() 方法直接指定this的绑定对象,如 foo.call(obj)
- new绑定:使用new来调用一个函数,会构造一个新对象并把这个新对象绑定到调用函数中的this
🏷️new绑定:
- 创建新的空对象
- 将this指向这个空对象
- 执行函数中的代码
- 没有显示返回非空对象时,默认返回这个对象
二、this指向
根据函数的调用方式的不同,this会指向不同的对象:
- 以函数的形式(包括普通函数、定时器函数、立即执行函数)调用时,this的指向永远都是window。比如fun();相当于window.fun();
- 以方法的形式调用时,this指向调用方法的那个对象
- 以构造函数的形式调用时,this指向实例对象
- 以事件绑定函数的形式调用时,this指向绑定事件的对象
- 使用call和apply调用时,this指向指定的那个对象
三、额外函数补充:apply、call、bind
1.apply和call
function foo(name, age, height) {
console.log("foo函数被调用", this)
console.log("参数", name, age, height)
}
foo("xxiaoming", 18, 120)
foo.apply("apply", ['xiaohong', 20, 150])
foo.call('call', 'xioalan', 17, 180)
apply调用:第一个参数:绑定this
第二个参数:传入额外的参数,以数组的形式
call调用:第一个参数:绑定this
第二个参数:参数列表,后续的参数以多参数的形式传递
2.bind
function foo(name, age, height) {
console.log("foo函数被调用", this)
console.log("参数", name, age, height)
}
var obj = {name: 'xiaoming'}
// 需求:调用foo函数时,总是绑定到obj对象身上(不希望obj对象身上有函数)
var bar = foo.bind(obj)
bar() // this -> obj
call与apply在改变this指向的同时就会立即执行函数,而bind绑定this后不会立马执行,而是返回一个新的绑定函数。
除此之外,bind属于硬绑定,即this指向与传进去的形参在bind方法执行的时候就已经确定了,无法再次改变,再运行这个函数,就相当于无参。
四、this绑定规则优先级
📝 显式绑定 > 隐式绑定 > 默认绑定
new绑定 > 隐式绑定 > 默认绑定
📝new绑定与显式绑定:
- new绑定不可以和 apply / call 一起使用,所以不存在谁的优先级更高
- new绑定优先级高于 bind
- 显式绑定中,bind 优先级高于apply / call
五、this规则之外
1、忽略显式绑定
apply / call / bind:当传入null / undefined 时,那么使用的规则是默认绑定,自动将this绑定程全局对象
2、间接函数引用
隐式绑定 谁调用,this就是谁
返回值是目标函数的引用
六、箭头函数
箭头函数允许我们用更短的语法定义函数。
箭头函数可用于替代传统函数function() { }
箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。
箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
1、箭头函数的缩写
1.如果箭头函数只有一个参数,那么 ()可以省略
names.forEach(item => { console.log(item) })
2.如果函数体中只有一行代码,那么大括号{ } 可以省略
names.forEach(item => console.log(item))
3.只有一行代码时,这行代码的表达式结果会作为函数的返回值返回的。
一行代码中,不能带return关键字,如果省略,需要带return一起省略
var newNums = nums.filter(item => item % 2 === 0)
4.如果默认返回值是一个对象,那么这个对象必须加 ( )
var bar = () => ({name: "haha", age: 17})
2、箭头函数中this使用
普通函数中是有this的标识符,而箭头函数中,压根没有this。通过apply调用时,也是没有this的
3、箭头函数中this应用
var obj = {
data: [],
getData: function() {
setTimeout(function() {
var result = ["abc","cba","nba"]
this.data = result
},2000)
}
}
obj.getData()
console.log(obj.data);//Array(0)
//此时obj拿不到result数组,
//因为this指向出了问题:setTimeout的this指向是window,此时obj的data仍是空数组
改进:
我们需要在外层定义:var _this = this
在setTimeout的回调函数中使用 _this 就代表了obj对象
var obj = {
data: [],
getData: function() {
var _this = this
setTimeout(function() {
var result = ["abc","cba","nba"]
_this.data = result
},1000)
}
}
obj.getData()
console.log(obj);
使用箭头函数:
var obj = {
data: [],
getData: function() {
setTimeout(() => {
var result = ["abc","cba","nba"];
this.data = result;
},1000)
}
}
obj.getData();
console.log(obj);
/*data: Array(3)
0: "abc"
1: "cba"
2: "nba"
length: 3
*/