this在前端开发中可以说是最常见的概念了,它其实也不难,但经常有人问起我this,我却不知从何说起,直到旁边的老哥跟我手敲代码解释起来,我终于对它的理解更加深刻了,下面想总结一下。
1、this的默认绑定场景
1.1 一般在函数调用时,打印this,,结果是window对象,这里可将this看作是函数的一个隐藏的变量。
function fn() {
console.log(this); //window
};
fn()
上面的函数其实类似于下面call(apply\bind类似)调用
function fn() {
console.log(this); //window
};
fn.apply(null)
1.2 在严格模式环境中,默认绑定的this指向undefined
function fn() {
"use strict";
console.log(this); //undefined
};
fn()
见下面例子:
function fn() {
console.log(this); //window
console.log(this.name);// lj
};
function fn1() {
"use strict";
console.log(this); //undefined
console.log(this.name);
};
var name = 'lj';
fn();
fn1() //报错 TypeError: Cannot read property 'a' of undefined
1.3 另外如果在严格模式下调用非严格模式中的函数,并不会影响this指向
var name = 'lj';
function fn() {
console.log(this); //window
console.log(this.name); // lj
};
(function () {
"use strict";
fn();
}());
2、this隐式绑定情况
2.1 隐式绑定到obj
function fn() {
console.log(this.name);
};
let obj = {
name: 'LIUJIE',
func: fn
};
obj.func() //LIUJIE
上面这个情况类似于为函数fn显式绑定到对象obj上
function fn() {
console.log(this.name);
}
let obj = {
name: 'LIUJIE',
};
fn.apply(obj); //'LIUJIE'
2.2 如果函数调用前存在多个对象,this指向会被最近的调用它的对象覆盖。
function fn() {
console.log(this.name);
};
let obj = {
name: '哈哈哈',
func: fn,
};
let obj1 = {
name: '刘洁',
o: obj
};
obj1.o.func() //哈哈哈
2.2 实例化构造函数,将this绑定到new出来的对象上,而不是window
function Person() {
console.log(this);//Person
}
var p = new Person();
3、call\apply\bind用法
- 1.call、apply与bind都用于改变this绑定,但call、apply在改变this指向的同时还会立即执行函数,而bind在改变this后是返回一个全新的boundFcuntion绑定函数,当你想调用时你再调用它。
3.2 bind属于硬绑定,返回的 boundFunction 的 this 指向无法再次通过bind、apply或 call 修改;call与apply的绑定只适用当前调用,调用完就没了,下次要用还得再次绑。(----这个我也是第一次听到的)
3.3 call与apply功能完全相同,唯一不同的是call方法传递函数调用形参是以散列形式,而apply方法的形参是一个数组。在传参的情况下,call的性能要高于apply,因为apply在执行时还要多一步解析数组。