由浅至深理解js中的this
this在Js中非常重要,要理解this如何让使用,首先要知道this到底是什么
this是Javascript语言的一个关键字,它是函数运行时自动生成的一个内部对象,只能在函数内部使用。this这个对象是谁,取决于函数被调用的方式
先按代码环境来分:
①全局作用域下:
这里this写在全局环境下,这时候等价于window对象。但在严格版中默认的this不再是window,而是undefined
②一般函数:
③构造函数:
首先new关键字会创建一个空的对象,在执行new之后,this会指向原型为a.prototype属性的空对象,然后a里面的this指针默认会作为返回值,所以acname变量会拥有name属性的值‘dov’
④对象方法:
这里对象obj里有一个属性f,值为一个函数,这时候在外部调用obj.f(),那么this指向对象obj,此时调用相当于obj.prop
再看一段
其实这段代码和前面差不多,obj.fuc为对象obj生成属性fuc,并赋值acname,实际上等于对象obj中生成了一个属性f并且值为函数acname,这时候o.f()依然返回obj.name
⑤对象原型链上:
这里对象y是x的实例,它的_proto_指向对象x,那么它就拥有了x的属性,这时候调用y.add()时,会先寻找x中是否包含方法add,如果没有就会往原型链上寻找,找到x中的方法add(),这时候由于add()是被对象y调用。所以函数f中的this指向对象y,并获取y的属性a、b对应的值。
下面来说一下this指针的call、applay、bind方法
函数对象从Function.prototype上继承到Function.prototype.call/Function.prototype.apply方法
call/apply方法最大的作用就是能改变this关键字的指向.
call
call()方法第一个参数为空,所以默认指向了window对象,所以sayName里面的this指向全局作用域下的name变量,获得‘dov’
再看一个例子
在这个例子中,b调用了a中的f(),将this绑定指向b中的n1、n2,所以在f()中this.n1='aaa'是赋值给b中的n1,this.n2='bbb'是赋值给b的n2
apply
apply和call用法几乎一摸一样,只是call的参数是要一个一个传,而apply的第二个参数是以数组形式传递
bind
bind是新创建一个函数,然后把它的上下文绑定到bind()括号中的参数上,然后将它返回。
所以,bind后函数不会执行,而只是返回一个改变了上下文的函数副本,而call和apply是直接执行函数。
可以看出,代码确实没有被打印,这就是bind和call、apply方法的不同,bind方法返回的是一个修改过后的函数。那么怎样才能成功获取出我们需要的结果呢?
调用成功打印‘dov’,同样bind也可以有多个参数,并且参数可以执行的时候再次添加,但是要注意的是,参数是按照形参的顺序进行的
call apply bind 都是绑定this指针的指向,call和apply是改变上下文中的this并立即执行这个函数,bind方法可以让对应的函数在时任意时候调用,并且可以在执行的时候添加参数
闭包中的this
看一段代码
闭包返回的是this.name。因为people是全局变量,在var people = person.getName()的时候,实际上是把代码变成了这样
于是this指向的是全局作用域上的name
ES6Arrow=>箭头函数中的this
①先看普通函数中的this
②箭头函数中的this
很明显普通函数的打印结果正是我们需要的,而箭头函数却并没有按照我们的期望打印结果,为什么两个函数打印出来的结果不一样呢?这里我们首先来理解一个概念:
JS 中每一个 function 有自己独立的运行上下文,而箭头函数不属于普通的 function,它没有独立的上下文,也没有自己的this。所以在箭头函数里写的 this
其实是包含该箭头函数最近的一个 function
上下文中的 this
(如果没有最近的 function
,就是全局),所以在上面这段代码中,箭头函数的this值继承自外部,我们将上面这段代码转换成ES5的写法,应该是下面这样的