关于JavaScript中万恶的this
什么是this?
定义:this是包含它的函数作为方法被调用时所属的对象。
说明:这句话有点咬嘴,但一个多余的字也没有,定义非常准确,我们可以分3部分来理解它!
1、包含它的函数。2、作为方法被调用时。3、所属的对象。
严格模式this的指向
"use strict";
console.log(this);//指向的window
function fn(){
console.log(this);//undefined
}
fn();
ES5非严格模式 全局中this和函数中this都指向window
ES5严格模式,ES6,全局中this仍然指向window,函数中this指向undefined
对象模式this的指向
var obj={
a:1,
b:function(){
console.log(this);//this不会因为变量引用改变而改变
this指向当前对象自身obj
console.log(obj.a);//变量会发生引用改变
},
c:this.a
// this指向对象外this的指向
// 对象没有创建完成时,this还没有生成,this就指向对象外this的指向
}
var o=obj;
obj={a:10,d:10}
o.b();
回调函数this的指向
var obj = {
a: function () {
console.log(this,"____");
var self=this;
function fn1(fn) {
fn();
arguments[0]();
fn.call(self);
}
function fn2() {
console.log(this);//window 回调函数中
// 1、如果直接指向的回调函数,this指向最外层window
// 2、如果通过arguments直接使用参数指向函数,this则指向执行当前函数的arguments
// 3、如果回调函数通过call,apply,bind重新指向了新的对象时,this就是指向新对象
}
fn1(fn2);
},
};
obj.a();
var obj={
b:1,
a:function(){
setTimeout(function(){
console.log(this);
}, 2000);
setTimeout(function(obj){
console.log(obj.b);
}, 2000,this);
}
}
obj.a();
事件中this的指向
var obj={
b:1,
a:function(){
// 特殊的回调函数
document.addEventListener("click",this.clickHandler);
},
clickHandler:function(e){
console.log(this);//事件侦听的对象 e.currentTarget
}
}
var obj={
b:1,
a:function(){
console.log(this);
// 特殊的回调函数
document.addEventListener("click",this.clickHandler);
document.attachEvent("onclick",this.clickHandler);
},
clickHandler:function(e){
console.log(this===document);//addEventListener事件侦听的对象 e.currentTarget
console.log(this===window);//IE8 attachEvent侦听事件时,this指向window
}
}
obj.a();
ES6类中的this
class Box{
static _instance;
constructor(){
console.log(this);//指向被实例化的对象
}
static getInstance(){
if(!Box._instance){
Box._instance=new Box();
}
return Box._instance;
}
play(){
console.log(this,"|");//指向被实例化的对象
}
static run(){
console.log(this);
console.log(this===Box,"____");
// this就是当前类名也是构造函数
// 任何的静态方法中this都是当前类
// 静态方法中无法获取到实例化对象的this的
return this;
}
static plays(){
this.getInstance().play();
var o=this.getInstance();
var o1=this.getInstance();
console.log(o===o1);
}
}
var b=new Box();//会执行构造函数,这是构造函数中this就是这个b对象
b.play();//b对象下的方法play,因此play方法中this被指向b,谁执行play,this指向谁
console.log(Box.run()===b);//false
console.log(Box.run()===b.constructor);//true
Box.plays();
ES5 面向对象中的this
function Box(){
console.log(this);
}
Box.prototype.play=function(){
console.log(this);//this是指向执行该方法的实例化对象
}
Box.run=function(){
console.log(this);//Box
}
Box();//this是window或者undefined
var b=new Box();// this是实例化后b对象
b.play();
箭头函数中的this
var obj = {
a: function () {
setTimeout(() => {
console.log(this);//this是箭头函数外this的指向
// 上下文环境中this的指向
}, 2000);
},
};
obj.a();
var obj={
a:function(){
document.addEventListener("click",this.clicHandler);
},
clicHandler:function(e){
setTimeout(()=>{
console.log(this);
},2000);
}
}
obj.a();
var obj={
a:function(){
console.log(this);//obj
},
b:()=>{
console.log(this);//window
}
}
obj.a();
obj.b();
function Box(){
}
Box.prototype.run=()=>{
console.log(this);//window
}
var b=new Box();
b.run();
call apply bind
function fn(){
console.log(this);
}
var obj={a:1}
fn.call(obj);//fn中this指向obj
fn.apply(obj);//fn中this 指向obj
fn.bind(obj)();//fn中this指向obj
var obj={
a:function(){
function fn(){
console.log(this);
}
fn();
console.log(this);//window 如果是call apply bind 带入的是null,将会把这里的this重新指向window
}
}
obj.a.call(null);
class Box{
constructor(){
}
play(){
var o={
run:function(){
function fns(){
console.log(this);
}
return fns;
},
play:function(fn){
fn();
arguments[0]();
},
clickHandler(){
// this 实例化的b
o.play.call(this,o.run());
}
}
document.addEventListener("click",o.clickHandler.bind(this));
}
}
var b=new Box();
b.play();
var obj={
a:10,
abc:function(){
setTimeout(()=>{
this.a++;
console.log(this.a,"_______");
(function(){
this.a++;
console.log(this.a);
}).call(this.c)
},1000);
},
c:{
a:20
}
}
obj.abc();
PS:如果想获取更多的知识视频,加QQ好友10398975免费送给大家