js 中 this总结
记录个人学习js总结,初学咋到,理解有不到位的地方,还请大家指正;
1、普通函数
-
普通函数function(){};中this指向调用该函数的对象,如果没有调用的对象,默认绑定到window全局对象;(es6中,let const 声明的全局变量不再在Window对象下了)
let test = "test"; console.log(this.test);//undefiend
-
对于this指向调用的对象,我比较喜欢这么理解,函数中的this的可以访问的作用域,就是该对象的内部作用域;
普通函数中this的指向问题可以分为4类,函数不同的声明方式。
-
通过new创建的函数,函数中this指向通过new方法创建处来的新实例对象;
function Person (a){ this.age = a; this.showAge = function () { console.log("age:",this.age);//10 console.log("this:",this);//指向person1 } } let person1 = new Person(10); person1.showAge();//10
-
显式声明的方式(通过call、apply绑定函数的执行对象,这么说不太准确,换个说法绑定函数的执行的作用域,这样函数中this就指向该作用域)
function a (){console.log("this:",this.name)}; let b = {name: 'b',} a.call(b);//b
-
隐式声明的方式,函数以属性值的方式存在,通过调用对象的属性来触发函数,此时函数指向调用的对象,this可以访问的作用域为 调用对象的内部作用域;
let obj = { name: 'jack', fun; function(){ console.log("this.name:",this.name); } } obj.fun();//this.name:jack;
-
当函数执行没有明确的调用对象时,则会绑定到window下,此时this指向Window;
function test(){ name: 'test', console.log("this.name:",this.name); } var name = "window"; //let name = 'let-window'; let 在script声明的变量不再是全局window下变量,此时为Script下 test();//this.name:window;
-
几种this 丢失的情况
-
引用赋值,通过引用赋值将函数赋值给新变量后执行,造成this指向丢失,从而指向window全局
let obj = { name: 'jack', fun; function(){ console.log("this.name:",this.name); } } var name = "window"; let test = obj.fun;// 将函数赋给test变量实则== let test = function(){ console.log("this.name:",this.name);} test();//window 此时函数没有明确的执行对象,此时this指向window全局
-
通过传参的方式,将函数作为另一个函数(父函数)的参数传入;比如定时器setTimeout(function(){},100);
let obj = { name: 'jack', fun; function(){ console.log("this.name:",this.name); } } var name = 'window'; setTimeout(obj.fun,100);//window; //100ms后定时器触发,执行obj.fun函数,我们知道定时器是js定义的全局函数,是window对象下的方法,所以调用定时器的对象是window全局对象;=》100ms后,obj.fun执行,此时执行对象是全局window,this的工作域或者说此时this可访问的作用域就是window,所以this.name = window
-
解决this丢失的方法,可以通过箭头函数或者bind、call、apply绑定函数的作用域(绑定函数的调用对象)
-
2、箭头函数
箭头函数 ()=> {}
箭头函数中的this指向定义该函数时父层函数的作用域
举两个例子:
1.
let obj = {
name: 'obj',
fun: function(){
let test = ()=>{
console.log("this.name:",this.name);
}
test();
}
}
var name = "window";
obj.fun();// obj; 箭头函数test()中的this指向定义该函数时父层函数所在的作用域,父层函数fun,父层函数所在的作用域是obj这个对象,this.name == obj;
2.
var obj = {
name: 'obj',
fun: ()=>{
console.log("this.name:",this.name);
}
}
var name = 'window';
obj.fun();// window;箭头函数fun 定义时父层为obj对象,父层所在的作用域为window全局作用域,所以箭头函数中this指向window;
bind、apply、call用法
同:js中改变this指向的方法,都是将普通函数强制绑定到指定对象的作用域中执行,使得函数中this的指向为该对象;
异:1.写法差异
- apply和call写法一致,bind()(),需要在绑定对象后再次执行,而前者无需;
- 传入的参数不同:call可以接收多个参数,apply只可以接受两个参数,第二个为数组;bind可以接收多个参数;
let a = {
name: 'a',
afun: function(arg1,arg2){ console.log("this:",this.name+"arg1:"+arg1+"-"+"arg2:"+arg2); //隐式调用
}
}
a.afun();//this指向对象a
let b = {
name: 'b',
}
let test11 = a.afun.bind(b,"bind1","bind2")();//bind方法:函数的工作域为b对象
let test111 = a.afun.bind(b)("bind1","bind2");//bind方法:函数的工作域为b对象
//都是将函数强制绑定到对象的作用域中执行,写法区别:bind()(); 绑定后需要再次执行
let test12 = a.afun.apply(b,["apply1","apply2"]);//第二个参数为数组形式,可以自动拆分
let test13 = a.afun.call(b,"call1","call2");//参数不限
博客参考学习 该篇博文:https://blog.csdn.net/qq_22855325/article/details/76267925