日常开发中,我们经常用到this。一开始常会用一种感觉去判断this的指向,当遇到复杂的函数调用时,就分不清this的指向。
今天我们来由浅入深来学习下。
function family1(){ var name = "小白"; console.log(this); //Window console.log(this.name); //undefined } family1(); // 等同于 window.family()
this指向的是调用它的对象,family处于全局,等同于 window.family(),此刻this等同于由window调用的, window中不存在name, 故为undefined
函数作为对象的一个属性
var family2 = { name:"小白", fn:function(){ console.log(this.name); //小白 } } family2.fn();
this指向的是对象family2,因为fn不仅作为一个对象family2的一个属性,而且是作为对象的一个属性被调用,即通过family2.fn()执行的。结果this就是对象family2。
var family2 = { name:"小白", fn:function(){
console.log(this) //window console.log(this.name); //undefined } } var newfn = family2.fn();
newfn();
如果fn函数被赋值到了另一个变量newfn中,并没有作为family2的一个属性被调用,那么this的值就是window,this.name为undefined。
构造函数中this,new实例化
如果函数作为构造函数用,那么其中的this就代表它即将new出来的对象。
function Fn(){ this.name = "小白",
console.log(this)
}
var family3 = new Fn();
console.log(family3.name); //小白
因为new关键字可以改变this的指向,将这个this指向对象family3, 变量family3创建了一个Fn的实例(相当于复制了一份Fn到对象family3里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象family3,那么this指向的自然是对象family3,那么为什么对象family3中会有name,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份。
function Fn(){ this.name = "小白", console.log(this) // window } Fn()
函数用call或者apply调用
当一个函数被call和apply调用时,this的值就取传入的对象的值。
我们通过几道题来练练手吧。
var a=11 function test1(){ this.a=22; console.log(this); //window,此时通过this修改了全局变量a的值,由11为22 let b = function(){ console.log(this); //window console.log(this.a); // 22 }; b(); } test1();
var a=11 function test1(){ console.log(this) // function test1() this.a=22; // 相当于给test1函数添加了 var a = 22 let b=function(){ console.log(this) //window console.log(this.a); // 11 }; b(); } var t = new test1();
以下几题进行对比
var val = 1; var obj = { val: 3, fun: function () { console.log(val); // 1 this.val *= 2; //this指向window,故window里面的window.val = val*2 console.log(val); // 2 val *= 2; //指window, window.val = val * 2 console.log(val); // 4 在 this.val *= 2的基础上再 val*2 console.log(this.val); // 4 } }; var objFun = obj.fun; objFun(); // 1 2 4 4
var val = 1; var obj = { val: 3, fun: function () { this.val *= 2; //this指向obj,故obj里面的obj.val = val*2 console.log(val); // 1 val *= 2; //指window, window.val = val * 2 console.log(val);// 此时val为1; 即 1*2 console.log(this.val); // this为obj; 此时val为3;即3*2 } }; obj.fun(); // 1 2 6
var val = 1; var obj = { val: 3, fun: function () { this.val *= 2; console.log(val); // 1 val *= 2; console.log(val);// console.log(this.val); // this为obj; 此时val为3;即3*2 } }; obj.fun(); // 1 2 6 var objFun = obj.fun; // 此时初始化window.val = 2; obj.val = 6 objFun(); // 4 8 8 注: 第一次调用后obj.fun影响第二次调用objFun
以下两个例子对比
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ console.log(this) // obj var that = this; return function(){ console.log(that) //obj return that.name; }; } }; console.log(object.getNameFunc()()); //My Object
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
console.log(this) // obj
return function(){
console.log(this) //window
return this.name;
};
}
};
console.log(object.getNameFunc()()); //The Window
object.getNameFunc()返回的是一个匿名函数,匿名函数的this是window
以下是英文原文:
Anonymous functions are not bound to an object in this context, meaning the this object points to window unless executing in strict mode (where this is undefined).
翻译:在这个上下文(执行环境)中匿名函数并没有绑定到任何一个对象中,意味着this指向window
(除非这个上下文(执行环境)是在严格模式‘use strict’下执行的,而严格模式下该this指向undefined)