概念
在红宝书描述:“this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this执行window,而当函数作为某个对象的方法调用时,this表示那个对象”。加粗的文字相对来说有点抽象,下面来介绍下this在不同的情境下都表示啥。
this分类
我把this指向情况大致可以分为以下7种:
- 普通函数的this
- 作为对象的this
- 构造器调用
- DOM事件的this
- 箭头函数的this
- 严格模式下的this
- call和apply修改的this
普通函数的this
当函数不作为对象的属性被调用时,这个函数我们就说是普通函数。在普通函数里,this总是指向全局变量(window)。
var name = 'zs';
var fn = function(){
return this.name;
}
console.log(fn()); //zs
或
var obj = {
name:"ls",
getName:function(){
return this.name
}
}
var getName = obj.getName;
console.log(getName()); //zs
/*
通过fn和getName函数来解析下“this对象是在运行时基于函数的执行环境绑定的”这句话:
fn执行时调用fn函数的执行环境时window,所以this执行window,这个相信大家没问题
var getName = obj.getName这句执行实际是把obj对象里面的函数复制一份给getName变量,此时等于
var getName = function(){return this.name},这时getName是一个普通函数。getName函数的实际调用是window(console.log(getName()))。所以此时this应该执行window,所以打印出来是zs
*/
紧扣上面的概念,下面在来看些其他例子
//假设有个div,给div添加一个点击事件
<div id="div1"></div>
________________________
window.id = "window"
document.getElementById("div1").onclick = function(){
console.log(this.id); //此时表示调用的对象,既div元素
//假设事件函数里面还有个函数
var callback = function(){
console.log(this.id); //window
}
callback()
}
//callback()被当作普通函数来执行,在普通函数中,this总是指向window的
——————————————————
//假设不想callback函数里里面的this指向全局,我们可以这样做
document.getElementById("div1").onclick = function(){
console.log(this.id); //此时表示调用的对象,既div元素
var that = thisl; //保存this
//假设事件函数里面还有个函数
var call = function(){
console.log(that.id); //div1
}
call()
}
作为对象的this
当函数作为对象的方法调用时,this表示这个对象的实例
let obj = {
name:'zs',
getName:function(){
console.log(this); //obj
}
}
构造器中的this
当我们使用new创建一个对象时,函数被当做构造器使用,默认情况下,构造器返回一个对象,这个对象就是this。
let Obj = function(){
this.name = 'zs';
//return this;
}
let o = new Obj();
console.log(o.name) //zs
那么我们可不可以修改构造器的返回值呢,答案是可以的。当返回值是一个对象时,这时this并不是我们期待的this了
function Obj(){
this.name = 'zs';
return {
name:'ls'
}
}
let o = new Obj();
console.log(o.name); //ls
但是如果构造器返回的不是一个对象呢,那么this还是我们期待的值,实例对象还是指向this
function Obj(){
this.name = 'zs'
return 'aaaa';
}
let o = new Obj()
console.log(o.name); //zs
DOM事件的this
在onclick和addEventerListener中 this 默认指向绑定事件的元素,但是IE比较奇异,使用attachEvent,里面的this默认指向window。
箭头函数的this
箭头函数是没有this的,在箭头函数里面的this,当前最近的非箭头函数的this,如果都没有找到,最终指向window,严格模式下undefined
let obj = {
a: function() {
let b = ()=>{
console.log(this)
}
b();
}
}
obj.a()
// 找到最近的非箭头函数a,a现在绑定着obj, 因此箭头函数中的this是obj
严格模式下this
"use strict";
function fn(){
console.log(this) //undefined
}
fn()
call和apply的this
call和apply的作用是用来修改this的指向的。这两者的区别在于传递的参数时不一样,call传递的参数必须是一个个展开的,apply传递的参数是用一个数组封装的
let obj = {
name:"zs",
getName:function(){
console.log(this.name)
}
}
let obj2 = {
name:"ls"
}
obj.getName(); //zs
obj.getName.call(obj2); //ls
obj.getName.apply(obj2); //ls