标签:contex 模式 foo def height 不用 pre col call
原答案地址:https://zhuanlan.zhihu.com/p/23804247
最开始,先看一下,为什么这里的this输出结果并不一样?
var obj = { foo: function (){ console.log("this-->>", this) } } var bar = obj.foo obj.foo() //打印出来的this是obj bar() //打印出来的this是window
一、函数调用
1、首先要从函数的调用讲起,JS里面有三种函数调用形式:
func(p1,p2)
obj.child.method(p1, p2)
func.call(context, p1, p2)
一般,我们知道前两种,并且认为前两种是优先于地上那种的。但实际上,第三种调用方式,才是正常的调用形式。
func.call(context, p1, p2)
其他两种方式是语法糖,可以等价地变换为call的形式。
func(p1, p2) //等价于 func.call(undefined, p1,p2) obj.child.method(p1, p2) //等价于 obj.child.method.call(obj.child, p1, p2)
因此,我们的函数调用只有一种形式:
func.call(context, p1, p2)
这样,this就好解释了:
this,就是上面的context。
this是你call一个函数时传的context, 由于你从来不用call形式的函数调用,所以你一直不知道。
先看func(p1, p2)里的this是如何确定的:
function func(){ console.log(this) } func() //等价于 function func(){ console.log(this) } func.call(undefined)
按道理来说,打印出来的this应该是undefined,但是浏览器有一条规则:
如果你传的context是null或者undefined,那么window对象就是默认的context(严格模式下默认context是undefined),因此,上面打印的结果是window。
如果你希望this不是window,很简单:
func.call(obj) //这里的this就会是obj对象了
2、再来看obj.child.method(p1, p2)里的this是如何确定指向的:
var obj = { foo: function(){ console.log(this) } }
obj.foo() //等价于 obj.foo.call(obj)
因此,this就是obj。
回到最开始的问题,obj.foo(),可以转化为obj.foo.call(obj), 因此,this就是obj。
bar()可以转化为 bar.call(), 由于没有传context,所以this就是undefined,根据浏览器默认原则,this指向的window。
二、 []语法
function fn(){console.log(this)} function fn2(){console.log("this-->>", this)} var arr = [fn, fn2] arr[0]()
想一下,arr[0]()这里的this指的是什么?
我们可以将arr[0]()想成arr.0(),虽然后者的语法错了,但是形式与转换代码里面的obj.child.method(p1, p2)对应上了,于是:
arr[0]()可以转化为:arr.0(),接着转化为arr.0.call(arr), 那么,this值得就是arr了。
三、箭头函数
如果你在箭头函数里看到this,直接把他当做箭头函数外面this即可。外面的this是什么,箭头函数里面的this就还是什么,因为箭头函数本身不支持this。
四、总结
1、this就是当你call一个函数的时候,传入的第一个参数。this就是call的第一个参数。
2、如果你的函数调用形式不是call形式,可以按照“转化代码”转换为call形式。
标签:contex 模式 foo def height 不用 pre col call
原文地址:https://www.cnblogs.com/qingshanyici/p/14284208.html