zoukankan      html  css  js  c++  java
  • javascript中关于this的理解

    首先看一下这几个定义

    • this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被视为某个对象的方法调用时,this等于那个对象。
      不过,匿名函数的执行环境具有全局性,因此其this对象通常指向window.

    • 每个函数在被调用的过程中都会自动取得两个特殊变量:this和arguemtns。内部函数在搜索这两个变量的时候,只会搜索到其活动对象为止,因此永远不可能访问外部函数中的这两个变量。

    • this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

    首先,先排除几个错误的认知:
    1、this对象是指向自身的。
    function foo(num){
    console.log(num);
    this.count++;
    }
    foo.count=0;
    for(var i=0;i<5;i++){
    foo(i)
    };
    console.log(foo.count); //0
    通过这个实例可以看出,count虽然被设置为了foo的属性。但是这里的this并不是指向foo自身的,因此当输出foo.count值的时候,其依然是0.

    2、this是指向自身的词法作用域的,也可以简单理解成对于变量对象的引用吧。
    function foo(){
    var a=2;
    console.log(this.a);
    }
    foo(); //undefined;
    我们在foo函数的作用域内定义了a的值为2,然而当我们输出a的值的时候却可以的到undefined,因此这样的理解也是不对的。

    实际上,this是在函数被调用时发生的绑定,它指向什么完全取决于在哪里调用。
    所以说,我们的第一步就是判断函数的调用位置。

     function baz(){
           //当前调用栈是:baz
           //因此,当前的调用位置是全局作用域
           console.log('baz');
           bar();//bar的调用位置
        }
    function bar(){
       //当前调用栈是baz->bar
       //因此调用位置是在baz中
       console.log('bar');
       foo();//<-foo的调用位置
    
    }
    function foo(){
       //目前调用栈是baz->bar->foo
       //因此,当前调用位置是在bar中
       console.log('foo')
    
    }
    baz();//<--baz的调用位置
    

    分析出了他们的调用位置之后,接下来就是要判断它是应用于哪种绑定规则的。
    1、默认绑定 独立函数调用-指向全局
    var a=2;
    function foo(){
    console.log(this.a);
    }
    foo(); //2
    这个例子中,函数的调用位置是全局环境,所以其指向全局即等于window(注意这是在非严格模式下)
    var a=2;
    function foo(){
    'use strict';
    console.log(this.a);
    }
    foo(); //undefined
    这时,由于严格模式的原因将会输出undefined;
    var a=100;
    function foo(){
    var a='foo中的a';
    bar();
    }
    function bar(){
    console.log(this.a);
    }
    foo();//100
    由调用位置决定的另外一个示例。

    2、隐式绑定 调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含。
    function foo(){
    console.log(this.a);
    }
    var obj={
    a:2,
    foo:foo
    }
    obj.foo(); //2
    当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象中。当然,也有一些隐式绑定的函数丢失绑定对象的问题,例如:
    var a='全局中的a';
    function foo(){
    console.log(this.a);
    }
    var obj={
    a:2,
    foo:foo
    }
    var s=obj.foo;
    s(); //全局中的a;
    s只是obj.foo的一个引用,而在当s调用的时候已经没有了上下文对象,因此将会默认绑定,从而输出‘全局中的a’
    还有一种情况:
    var a='全局中的a';
    function s(fn){
    fn();<--调用位置
    }
    function foo(){
    console.log(this.a);
    }
    var obj={
    a:2,
    foo:foo
    }
    s(obj.foo);
    fn只是引用了obj.foo,而在obj.foo的调用位置没有任何特殊绑定,所以是默认绑定指向全局。

    3、显式绑定 用call/apply方法。
    function foo(){
    console.log(this.a);
    }
    var obj={
    a:'董志强',
    foo:foo
    }
    foo.call(obj);
    //通过foo.call(..),我们可以在调用foo时强制把他的this绑定到obj上。

    4、new绑定
    1创建一个新对象
    2这个对象会被执行[proto]连接
    3这个新对象会绑定到函数调用的this.
    4如果函数没有返回其他对象,那么new表达式中的函数会自动返回这个新对象。
    function foo(a){
    this.a=a;
    }
    var b=new foo(2);
    console.log(bar.a);//2

    大概就是这样子的吧,判断出具体的位置之后,再判断绑定方式,这样就可以判断出this的指向了。也有一些例外情况,例如foo.call(null)或者foo.apply(undefined)的情况,在没有其他绑定的情况下,这时foo函数里面的this是指向全局的。

    这时你会发现是不是好多问题都理解更深刻了,像下面,.
    function Person(name,age){
    this.name='dong';
    this.age=29
    }
    Person.prototype.z=2;

    var person=new Person();
    alert(person.z);//2
    alert(person.name);//'dong'
    都知道,person.z是person对象沿着原型链向上查找得到的,因为Person.prototype属性里面有z这个属性。
    而对于name和age来说他们,则是new绑定,this会指向当前new的对象,所以相当于自身创建了name和age这两个属性,而不是向上查找得到的。

  • 相关阅读:
    mysql中的内置函数
    python之旅九【第九篇】socket
    docker的安装,升级,与删除(最新版)
    consul与docker的使用
    python之旅第八篇--异常
    python的图形模块PIL小记
    python之旅七【第七篇】面向对象之类成员
    python之旅六【第七篇】面向对象
    zabbix上监控docker
    zabbix在ubuntu16.04上的安装
  • 原文地址:https://www.cnblogs.com/qqqiangqiang/p/5316973.html
Copyright © 2011-2022 走看看