javascript 之this指针-11

 前言

以《javascript
之行环境-08》文中说及,当JavaScript代码执行一截可尽代码时,会创对应之推行上下文(execution
context)。对于每个执行上下文,都出三个重大性质:

  • 变量对象(Variable object,VO)
  • 图域链(Scope chain)
  • this

JavaScript中的this同其他语言稍微不平等,比如Java .net言语中之this大凡在代码的尽阶段是不可变的,而JavaScript的this凡是当调用阶段展开绑定。也因及时同样属性为了this好十分之油滑,即当函数在不同之调用方式下都可能会见招致this的价值不同;

定义

  this
对象是以运转时根据函数的实行环境绑定的,跟函数的调用位置有关而非是声称的职;可以掌握为this是以函数调用阶段绑定,也便是行上下文创建的等级展开赋值,保存于变量对象吃;

季种绑定规则

new 构造函数绑定,this指于新创建的对象

 1 function createPerson(){
 2        return new person();
 3     }
 4     function person() {
 5         this.name = "Joel";
 6         this.say=function(){
 7             console.log(p)
 8             console.log('hello' + this.name)
 9         }
10     }
11     var p = new person();
12     p.say();
13     console.log(p.name);//Joel
14     console.log('开始')
15     var t=createPerson();
16     t.say();

无是直new 还是通过function createPerson 函数回的对象,this
都是凭借为了新创建出来的靶子;

亮绑定,this指为污染进的对象

 1     //call() apply() bind() 显示绑定
 2     window.color = "red";
 3     var Obj = { color: "blue" };
 4     function sayColor() {
 5         console.log(this.color);
 6     }
 7     sayColor();// red this window
 8     sayColor.call(this);//red
 9     sayColor.call(window);//red
10     sayColor.call(Obj);// blue 把this指针改为对象Obj
11     sayColor.apply(Obj);//blue 把this指针改为对象Obj
12     sayColor.bind(Obj)();//blue 把this指针改为对象Obj

比方你把null/undefined作为this的绑定对象传入call/apply/bind,这些价值在调用时会见给忽视,实际用底是默认的绑定规则;

1   function foo() {
2       console.log(this.a)
3     }
4    var a=2;
5     foo.call(null);//2
6     foo.call(undefined);//2

隐士绑定

因目标的法子形式调用,this指向当前此目标

 1    function foo(){
 2         console.log(this)//{a: 2, name: "Joel", foo: ƒ}
 3         console.log(this.a)//2
 4     }
 5     var obj={
 6         a:2,
 7         name:'Joel',
 8         foo:foo
 9     };
10     obj.foo();

此刻this指向当前obj对象,但是一旦换种写法会导致this 丢失问题。

 1     function foo(){
 2         console.log(this)//{a: 2, name: "Joel", foo: ƒ}
 3         console.log(this.a)//2
 4     }
 5     var obj={
 6         a:2,
 7         name:'Joel',
 8         foo:foo
 9     };
10     obj.foo();
11     //this 丢失的问题
12     var t= obj.foo;
13     t(); //window undefined

变量t此时封存之是函数的援跟obj已经没有关系,所以这时this指为window。

默认绑定 严格模式下this 绑定到undefined,否则绑定到全局对象 window

 1   function foo(){
 2         console.log(this)//window
 3         console.log(this.a)//Joel
 4     }
 5     var a='Joel';
 6     foo();
 7 
 8     //严格模式
 9     function fo(){
10         'use strict'  //严格模式
11         console.log(this)//undefined
12         console.log(this.b)//报错 Cannot read property 'b' of undefined
13     }
14     var b='Joel';
15     fo();

如上是主导的this绑定规则,其中new、显示绑定好爱看清,其中比较易于摩擦的是善把默认绑定误认为是隐士绑定
如匿名函数、闭包、函数当做参数等;

独调用:this 指向window

 1   var name='Joel',age=12;
 2     function say(){
 3         function say1(){
 4             console.log(this.name);//window
 5             function say2(){
 6                 name+='-l'
 7                 console.log(this.name);//window
 8             }
 9             say2()
10         }
11         say1();
12     }
13     say();
14 
15     //匿名函数
16     (function(){
17        console.log(this.name)
18     })()

function 当做参数传递其实与独立调用一样的原理

 1 function foo() {
 2         console.log(this)//window
 3         console.log(this.a)//oops global
 4     }
 5     function doFoo(fn) {
 6         console.log(this);//window
 7         fn();//类似与 foo()
 8     }
 9     var obj = {
10         a: 2,
11         foo: foo
12     }
13     var a = 'oops global';
14     doFoo(obj.foo);

和理setTimeout 也是同

 1  var obj = {
 2         a: 2,
 3         foo: function() {
 4             console.log(this); 
 5         },
 6         foo2: function() {
 7             console.log(this);   //this 指向 obj 
 8             setTimeout(this.foo, 1000);   // this 指向 window 
 9         }
10     }
11     var a = 'oops global';
12     obj.foo2();

闭包中的this

 1     var name = "Joel";
 2     var obj = {
 3         name: "My object",
 4         getName: function() {
 5             // var that = this;   // 将getNameFunc()的this保存在that变量中
 6             return function() {
 7                 return this.name;
 8             };
 9         }
10     }
11     console.log(obj.getName()());   // "Joel"

此的虽然是目标的道形式调用obj.getName(),在getName中之this是指为obj,但是回到的匿名函数中之this
为什么是window呢?

将最终之平等句子拆成稀独步骤执行:

1 var t=obj.getName();
2 t();

是休是来接触像在独立调用呢?如果急需拜访obj中的name,只待拿this对象缓存起来,在匿名函数中访问即可,把var
that=this;去丢注释即可;

总结

  • this
    是变量对象的一个性,是在调用时被绑定的,跟函数的调用位置有关而无是声称的职;
  • 找到调用位置,根据绑定规则来分析this 绑定;
  • 默认绑定严格模式下this 绑定到undefined,否则绑定到全局对象 window;

思考题

 1     var length = 5;
 2     var obj = {
 3         foo: function (fn) {
 4             console.log(this.length); // this => obj
 5             fn(); // this => window
 6             arguments[0](); // this => arguments
 7             var bar = arguments[0];
 8             bar(); // this => window
 9         },
10         length: 10
11     }
12     var fn = function () {
13         console.log(this.length);
14     }
15     obj.foo(fn);
16     //10, 5, 1, 5