无论项目开发还是应付面试,this指向问题你都没办法回避,花几分钟搞定它!我尽可能的用简单的语言来描述。
1. 默认this绑定window
当在全局的上下文中调用this,此时this指向是默认的window。
<body>
<script>
let name = '哈哈'
console.log(this) //这里的this 处于全局上下文 指向的便是window
console.log(this.name) // 此时this.name 相当于window.name, 即全局作用域下的name ‘哈哈’
</script>
</body>
输出结果为:
2. 隐式绑定this
隐式绑定是指,谁调用就指向谁!
(其实与第一种默认绑定原理相同,第一种就是在window对象中调用的this)
<body>
<script>
let name = '哈哈'
let obj = {
name:"嘿嘿",
getName: function(){
console.log(this.name) // 此时的this便是obj , 因此输出是嘿嘿
}
}
obj.getName()
</script>
</body>
注意:
如果再getName中再加一个函数,test()
<body>
<script>
let name = '哈哈'
let obj = {
name:"嘿嘿",
getName: function(){
console.log(this)
console.log(this.name)
function test(){
console.log(this)
console.log(this.name)
}
test()
}
}
obj.getName()
</script>
</body>
输出结果如下:
这表明,getName中的this指向的是obj,但test()中的this指向的是window! 也就是说虽然test()在getNmae内部,但两个this没关系,仍然是谁调用指向谁,test()没有指明调用者相当于默认为window。
另外补充几个特例:
<script>
// 一些api可以指定this指向
var obj2 = {
name:"嘻嘻"}
var arr=[1,2,12]
// 对于arr.forEach 函数 ,当不传第二个参数时,默认this指向window
arr.forEach(function(item,index,arr){
console.log(this)
})
// 当有第二个参数时,指向指定的obj2
arr.forEach(function(item,index,arr){
console.log(this)
},obj2)
// sort 也是指向window
arr.sort(function(){
console.log(this)
})
</script>
结果:
3. 显式绑定 call、apply、bind
三者都是用来显式指定this的指向,主要区别在于传参方式不同
<script>
console.log('88888')
var obj3 = {
name:'吼吼'
}
function f3(a,b,c){
console.log(a,b,c)
console.log("我的this是",this)
}
f3(1,2,3)
f3.call(obj3,4,5,"call")
f3.apply(obj3,[4,5,"apply"])
f3.bind(obj3)(4,5,"bind") // bind特殊点是,其返回的是个函数
</script>
执行结果:
注:当指定的对象不存在时,this仍指向默认的window
比如:call(undefind)
4. new绑定
指使用构造函数创建对象时,this指向新创建的对象
var obj = new foo()
这时this指向新创建的对象obj
扫描二维码关注公众号,回复:
13125365 查看本文章

5. 优先级 new>显式>隐式>默认
6. 箭头函数
箭头函数是ES6新增的创建函数方法。但箭头函数和普通函数不同,箭头函数内部是没有this的指向的,箭头函数中的this实际上是向外层一级一级的查找作用域中的this(直到this有定义)
看代码比较好理解:
<script>
console.log("箭头函数")
function foo(){
console.log(this) // 因被obj4调用,所以this指的是obj4
var test2 = function(){
console.log(this) // 上面以及分析过了,此处指的是 window
}
var test = ()=> {
console.log(this) // 但是这里的this 指向的仍是 obj4 与父级作用域的this是相同的
}
test()
test2()
}
var obj4 = {
a:"哦哦",
foo:foo
}
obj4.foo()
</script>