JavaScript深入浅出-this

this跟作用域并没有什么关系,this指向的是调用者!自己已经踏入这个坑好多次了…总是以为this跟作用域有关系.

全局的this(浏览器)

console.log(this)//window 
console.log(this===window)//true 
this.a=37; 
console.log(window.a)//37 

一般函数的this(浏览器)

function f1(){ 
   return this 
} 
f1()===window//true,global object 
--- 
function f2(){ 
   'use strict'; 
   return this 
} 
f2()===undefined;//true 

作为对象方法的函数this

var o={ 
   prop:37, 
   f:function(){ 
       return this.prop 
   } 
} 
console.log(o.f());//logs 37 
--- 
var o={prop:37}; 
function independent(){ 
   return this.prop 
} 
o.f=independent; 
console.log(o.f())//logs 37 

对象原型链上的this

var o={ 
   f:function(){ 
       return this.a+this.b 
   } 
} 
var p=Object.create(o); 
p.a=1; 
p.b=4; 
console.log(p.f());//5 

p的原型是o,p.f()调用的是原型链上的方法,当调用的时候原型链上的this也可以指向p这个对象

get/set方法与this

function modulus(){ 
   return Math.sqrt(this.re*this.re+this.im*this.im) 
} 
var o={ 
   re:1, 
   im:-1, 
   get phase(){ 
       return Math.atan2(this.im,this.re); 
   } 
} 
Object.defineProperty(o,'modulus',{ 
   get:modulus, 
   enumerable:true, 
   configurable:true 
   }) 
console.log(o.phase,o.modulus);//logs -0.78 1.4142 

get,set方法会指向对象方法,get中间不要用:分割

构造器中的this

function MyClass(){ 
   this.a=37; 
} 
var o=new MyClass(); 
console.log(0.a);//37 

function C2(){ 
   this.a=37; 
   return { 
       a:38 
   } 
} 
o=new C2(); 
console.log(0.a)//38 

用new作为构造器去构造,this会指向MyClass空对象,默认的this会作为返回值,C2中 new构造的时候this会指向原型为MyClass.prototype这样一个空对象,最后函数的返回值,如果没写return或者return基本类型 会将this作为返回值,如果返回的是一个对象,会将对象作为返回值在构建的时候也就是o=new C2()其中this指向的是MyClass但构建完毕后也就是单独执行o;会this指向return的object

call/apply方法中的this

function add(c,d){ 
   return this.a+this.b+c+d; 
} 
var o={a:1,b:3}; 
add.call(o,5,7);//1+3+5+7=16 

add.apply(0,[10,20]);//1+3+10+20=34 

function bar(){ 
   console.log(Object.prototype.toString.call(this)) 
} 
bar.call(7)//'[object Number]' 

改变函数的this指向 原本bar 函数this指向的是window,传递了一个7也就是this指向了[object Number]

bind方法与this

function f(){ 
   return this.a; 
} 
var g=f.bind({a:'test'}); 
console.log(g())//test; 

var o={a:37,f:f,g:g}; 

console.log(o.f(),o.g());//37,test 

bind不会对原方法的作用域进行修改,仅仅是针对bind调用者/赋值者进行绑定