this做为JavaScript中一个大难点,不少初学者一开始都理解不了,或者理解不许确之类的。我在看了《javascript高级程序设计》以及一些大佬的博客后,对this有了新的认识,因而写下来供你们参考。若是该博客有什么错误的地方,请读者指正。javascript
this的指向在函数定义的时候是肯定不了的,只有函数执行的时候才肯定this到底指向谁,实际上this的最终指向的是最后调用它的对象
java
因而就延伸出了肯定this指向的几种方法:数组
虽然上面说的并无错,可是这么多种状况,在实际应用中也不必定可以准确的对应上,咱们不如来学一下this的原理,这样遇到问题也能够本身分析。bash
在接下来的实例讲解中,我将函数分为 箭头函数
与非箭头函数
。在非箭头函数
中,this是做为一个隐式的参数传入,而在箭头函数
中,this与其余变量一视同仁,不会被特殊处理。app
function a(){
var name='ming';
var age=13;
console.log(this.name,age);
}
var name='ye';
var age=15;
a(); //输出的结果是ye 13
复制代码
咱们来分析一下:函数
a()做为一个普通的函数,
this
是做为一个隐式的参数传入到函数参数中。它完整的写法应该是window.a.call(window)
;因为咱们没有显式的调用call
来指定this
的指向,那么JS就会帮咱们完成这一步,让调用该函数的对象做为this
。因此this
在这里指向的是window
; 而函数的参数是在调用时候才肯定的,因此this.name
输出的是ye;可是对于age,他在函数里面只是一个普通的变量,加上做用域链的查找规则,会使用离他最近的变量。与会这里的age
会输出13。学习
var name='outter';
let obj={
name:'jack',
say(){
console.log(this.name)
};
};
(1) obj.say(); //输出的结果为'jack'
let c=obj.say
(2) c() //这里输出的是outter;
复制代码
咱们先来看一下第一个输出结果。 经过对象
obj
来调用say方法
,这段代码至关于obj.say.call(obj)
。由于不经过call
强行指定this
指向,那么JS会默认帮咱们把this
指向调用它的对象,因此输出的结果是jack
。ui
第二个输出结果咱们来看看上面的内存图,
变量C
保存的是say
的地址,也就是说咱们调用C的时候,并不通过obj
的影响,那么这种状况也是至关于window.c.call(window)
,因此JS默认状况下会让this
指向调用它的对象,也就是全局对象window
。this
注意!!!spa
注意!!!
注意!!!
这里有一个须要注意的地方,当var name='outter'
改成let name='outter'
的时候,状况却变了。
let name='outter'
let obj={
name:'jack',
say(){
console.log(this.name)
}
}
let c=obj.say
c() //输出的结果是undefined
复制代码
这是由于let
声明的变量并无成为window
的变量,而var
声明的变量成为了window
的变量,因此this指向的对象window
并无name
这个属性
var obj1={
name:'pony',
say(num=''){
console.log(this.name+num)
}
}
var obj2={
name:'jack'
}
(1) obj1.say() //输出pony
(2) obj1.say.call(obj2,2) //输出jack2
(3) obj1.say.apply(obj2,[2]) //输出jack2
复制代码
call
与apply
的最大区别就是apply
传入参数须要放在一个数组里面。 这里经过call
显式的指定this
的指向,因而这里就把obj2
做为say
的调用对象了。那么你可能会有疑问,为何个人say
写在obj1
里面,用call
就能够改变指向呢。这个只是刚好say
写在了obj1
里面而已。
var name='one'
let a=function f1(){
console.log(this.name)
}
function f1(){
var name='inner'
a()
}
f1() //输出的结果为one,而不是inner
复制代码
箭头函数不绑定this,他会捕捉定义的位置或者做用域链上最近的this,做为本身的this。因此 call() / apply() / bind() 方法对于箭头函数来讲只是传入参数,对它的 this 毫无影响。
注意,{}并不会造成一个做用域,在JS中只有全局做用域与函数生成的局部做用域。
var i=10;
var a={
i:20,
b:()=>{
console.log(this.i)
},
c:function(){
console.log(this.i)
}
}
a.b() //输出10
a.b.call(a) //输出10
a.c() //输出20
复制代码
由于
{}
并不会造成做用域,箭头函数沿着做用域链向上查找,在全局做用域找到了i
,因而返回全局做用域的i
,因为箭头函数并无绑定this
,因此使用call
指定也是没有办法改变this
,由于它压根没有this
。而对于a.c(),做为非箭头函数,上面的例子已经解析了。
var i=10
function f1(){
i=12;
var f=()=>{
console.log(this.i)
}
f()
}
f1() //输出12
复制代码
由于函数会造成局部做用域,箭头函数查找的时候,在
f1
的做用域就能找到i
了。
以上为我的学习整理的内容,所有的例子都是通过我的检验的,欢迎一块儿交流学习。