浅谈this指向
一.js中的特殊对象:
首先先看以下js中有哪些特殊的对象:
1.this对象:
本文要说的对象,比较特殊,使用环境不同,它的指向也不同。
2. window对象:
Window 对象表示浏览器中打开的窗口。
在客户端浏览器中,window 对象是访问 BOM 的接口,如引用 document 对象的 document 属性,引用自身的 window 和 self 属性等。同时 window 也为客户端 JavaScript 提供全局作用域。
Window 对象表示一个浏览器窗口或一个框架。在客户端 JavaScript 中,Window对象是全局对象,所有的表达式都在当前的环境中计算。也就是说,要引用当前窗口根本不需要特殊的语法,可以把那个窗口的属性作为全局变量来使用。例如,可以只写 document,而不必写 window.document。
3.arguments对象:
arguments 是一个对应于传递给函数的参数的类数组对象。
arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。
二.this指向问题:
1. 事件函数:
event handlers(事件处理函数),响应于某个事件而调用的函数。像那种点击事件,键盘事件。此时this指向这个事件元素本身。
如,有一个按钮点击事件:
<body>
<button id="btn"></button>
<script>
var btn = document.querySelector('#btn');
//点击事件
btn.addEventListener('click',function(){
console.log(this);
console.log(btn);
console.log(this === btn);
})
</script>
</body>
我们看输出,this与btn对应什么,与它们是否相等:
可以看出此时this指向这个事件元素本身。
2. 全局函数:
全局对象中,this默认指向全局。
如:
<script>
function night(){
console.log(this);
console.log(this===window);
}
// 你看,它此时是被 window 引用的。
night();
</script>
运行结果可以看出它是指向全局的:
当然,这只是默认情况下,如果它是被一个具名函数引用,则指向引用它的本身。
如:
<button id="btn"></button>
<script>
var btn = document.querySelector('#btn');
function night(){
console.log(this);
console.log(this===window);
}
// 此时它被这个按钮引用
btn.onclick = night;
</script>
可以看出此时这个this指向的是btn这个按钮:
3.对象:
哪个对象调用了函数,该函数里面的this就指向谁。
<script>
function night(){
return this;
}
// 建一个对象
var obj = {};
//给对象设置一个属性printThis,调用night这个函数
obj.printThis = night;
</script>
可以看出 night 函数中 this 指向 obj 这个对象 :
4.构造函数:
构造函数中的 this, 指向了由构造函数实例化的对象。
<script>
//定义一个构造函数
function People(name,age){
this.name = name;
this.age = age;
this.say = function(){
return "Hello world !"
}
this.printThis = function(){
//返回 this
return this;
}
}
// 实例化
var people = new People('小明',21);
</script>
this指向了实例化的people对象。
5.apply和call方法:
call() 方法与apply()方法非常相似,这两个方法都是用来改变对象的引用,能够编写用于不同对象的方法。不同之处在于传递的参数不同,参数中,第一个都是要改变的引用对象,其它多个参数一个是使用逗号分隔参数的参数列表,另一个是使用一个包含多个参数的数组。当然如果不需要传参数就不用了。
先看一般情况,obj2.printThis()里的 this 肯定是指向它自己里的name ‘joy’
<script>
var obj = {
name: 'sam'
}
var obj2 = {
name:'joy',
printThis: function(){
return this.name;
}
}
console.log(obj2.printThis());
</script>
输出结果:
通过apply方法改变obj2对象下的printThis函数的调用,this的指向改变为obj:
<script>
var obj = {
name: 'sam'
}
var obj2 = {
name:'joy',
printThis: function(){
return this.name;
}
}
// 通过apply方法改变obj2对象下的printThis函数的调用,this的指向改变
console.log(obj2.printThis.apply(obj));
</script>
结果:
6.箭头函数:
箭头函数this是静态的,this始终指向函数声明时所在作用域下的this值:
//全局
window.name = 'night';
//对象里的
var peopel = {
name:'sky'
}
//普通函数
function getName1(){
console.log(this.name);
}
//箭头函数
let getName2 = ()=>{
console.log(this.name);
}
//分别调用
getName1.call(peopel);
getName2.call(peopel);
运行结果:
因为call()方法,看出getName1的this指向已经变了,不再是全局的name,而是people对象里的name,而箭头函数getName2没变,因为它始终指向函数声明时所在作用域下的this值。
三.总结:
总的来说,this的指向不是在函数声明时确定的,而是在调用执行时确定的,同时,this不同的指向在于遵循了一定的规则。
1.默认情况下,指向全局,浏览器的话就是指向window。
2.如果函数被调用的位置存在上下文,那么函数被隐式绑定。
3.如果存在构造函数,this指向new 的这个新对象。
4.箭头函数的是没有属于自己的this的,它会继承父作用域的this,所以它是在声明时确定的。同时,它不可以new,也没有arguments,也不能用call、bind改变。
5.call,apply能改变this的指向。
- 点赞
- 收藏
- 关注作者
评论(0)