前言
this是执行上下文环境的一个属性,而不是某个变量对象的属性。
在全局代码中,this始终是全局对象本身,这样就有可能间接的引用到它了。
在通常的函数调用中,this是由激活上下文代码的调用者来提供的,即调用函数的父上下文(parent context )。this取决于调用函数的方式。
function函数里的this指向,由函数的调用方式决定:
- 如果
new
关键词出现在被调用函数的前面,那么JavaScript引擎会创建一个新的对象,那么函数中的this
指向的就是这个新创建的对象; - 如果通过
bind
的方式得到的函数,那么该函数中的this
指向bind
的第一个参数; - 如果通过
apply
、call
的方式触发函数,那么函数中的this
指向传入函数的第一个参数; - 如果通过某个对象使用句点符号触发函数,那么函数中的
this
指向该对象; - 如果直接触发函数,那么函数中的
this
指向全局对象(在浏览器中指向window
,在node.js中指向global
);
非函数里的this指向:
- 不在函数里的this指向全局对象(在浏览器中指向
window
,在node.js中指向global);
详细分析this指向的这5种情况:
1、new 关键字,作为构造器调用的函数中的this
如果
new
关键词出现在被调用函数的前面,那么JavaScript
引擎会创建一个新的对象,那么函数中的this
指向的就是这个新创建的对象;
function Cat(name) {
var _this = this;
this.name = name;
this.test = function() {
console.log(`this equal _this: ${_this === this}`);
console.log(`this euqal window: ${this === window}`);
}
}
var mi = new Cat('mi');
mi.test(); // "this equal _this: true"
// "this euqal window: false"
var test1 = mi.test;
test1();// "this equal _this: false"
// "this euqal window: true"
复制代码
2、bind 指定this
var obj2 = {};
function thisFunc2() {
console.log(`this2 equal window: ${this===window}`);
console.log(`this2 equal obj2: ${this===obj2}`);
};
var thisFunc22 = thisFunc2.bind(obj2);
thisFunc2();// "this2 equal window: true"
// "this2 equal obj2: false"
thisFunc22();// "this2 equal window: false"
// "this2 equal obj2: true"
复制代码
3、call、apply重定向this
如果通过
apply
、call
的方式触发函数,那么函数中的this
指向传入函数的第一个参数;
var GlobalName = 'globalName';
var obj3 = 'sofia';
function thisFunc3(a) {
console.log(`this3'Name: ${this}`);
console.log(`a: ${a}`);
}
var thisFun33 = thisFunc3.bind(obj3, 4);
thisFun33.call(GlobalName, 3);// "this3'Name: sofia"
// "a: 4"
thisFun33();// "this3'Name: sofia"
// "a: 4"
复制代码
4、对象属性的方法
var obj4 = {
thisFunc4: function () {
console.log(`this4 equal obj4: ${this===obj4}`);
}
};
obj4.thisFunc4(); // "this4 equal obj4: true"
复制代码
var obj5 = {};
function thisFunc5 () {
console.log(`this5 equal obj5: ${this===obj5}`);
}
obj5.thisFunc5 = thisFunc5;
obj5.thisFunc5(); // "this5 equal obj5: true"
复制代码
var obj6 = {};
obj6.thisFunc6 = function () {
console.log(`this6 equal obj6: ${this===obj6}`);
}
obj6.thisFunc6(); // "this6 equal obj6: true"
复制代码
var obj7 = {}, obj77 = {};
obj7.thisFunc7 = function () {
console.log(`this7 equal obj7: ${this===obj7}`);
console.log(`this7 equal obj77: ${this===obj77}`);
}
var thisFunc77 = obj7.thisFunc7.bind(obj77)
thisFunc77();
// "this7 equal obj7: false"
// "this7 equal obj77: true"
复制代码
5、直接调用
function thisFunc1() {
console.log(`this1 equal window: ${this===window}`);
};
thisFunc1(); // "this1 equal window: true"
复制代码
或者换种写法:
var obj8 = {
thisFunc8: function(){
console.log(`this8 equal obj8: ${this===obj8}`);
console.log(`this8 equal window: ${this===window}`);
}
}
obj8.thisFunc9 = thisFunc77;
obj8.thisFunc9();
// "this7 equal obj7: false"
// "this7 equal obj77: true"
var thisFunc88 = obj8.thisFunc8;
thisFunc88();
// "this8 equal obj8: false"
// "this8 equal window: true"
复制代码
this指向了解测试
题目1. this指针
function logName(){
console.log(this.name);
}
function doFun1(fn){
fn();
}
function doFun2(o){
o.logName();
}
var obj = {
name: "LiLei",
logName: logName
};
var name = "HanMeiMei";
doFun1(obj.logName);
doFun2(obj);
复制代码
结果
HanMeiMei
--------------------------------------------
LiLei
复制代码
题目2.call、apply修改this指向
function fun(somthing) {
console.log(`name: ${this.name}, somthing: ${somthing}`);
};
function bindFun(fn, obj) {
return function () {
return fn.apply(obj, arguments);
}
}
var obj = { name: "LiLei" };
var bar = bindFun(fun, obj);
console.log(bar);
var b = bar('Sofia');
复制代码
结果
function () {
return fn.apply(obj, arguments);
}
--------------------------------------------
name: LiLei, somthing: Sofia
复制代码
题目3.立即执行函数
function logName() {
console.log(this);
console.log(this.name);
}
var name = "XiaoMing";
var LiLei = { name: "LiLei", logName: logName };
var HanMeiMei = { name: "HanMeiMei" };
(HanMeiMei.logName = LiLei.logName)();
复制代码
结果
window
--------------------------------------------
XiaoMing
复制代码