<sup id="sjju3"><noscript id="sjju3"></noscript></sup>
    <big id="sjju3"></big>

  • <blockquote id="sjju3"></blockquote>
    <blockquote id="sjju3"></blockquote>

      <td id="sjju3"></td>

      <big id="sjju3"></big>
        <code id="sjju3"><strong id="sjju3"><dl id="sjju3"></dl></strong></code>
      1. Javascript的this详解

         更新时间:2019年03月23日 17:19:19   作者:蓝染   我要评论

        这篇文章主要介绍了Javascript的this的作用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

        在理解javascript的this之前,首先先了解一下作用域。

        作用域分为两种:

        1. 1、词法作用域:引擎在当前作用域或者嵌套的子作用域查找具有名称标识符的变量。(引擎如何查找和在哪查找。定义过程发生在代码书写阶段)
        2. 2、动态作用域:在运行时被动态确定的作用域。

        词法作用域?#25237;?#24577;作用域的区别是:词法作用域是在写代码或定义时确定的;动态作用域是在运行时确定的。

        this的绑定规则

        this是在调用时被绑定,取决于函数的调用位置。由此可以知道,一般情况下(非?#32454;?#27169;式下),this都会根据函数调用(调用栈)的上下文来绑定对象。

        一、默?#20064;?#23450;

        默?#20064;?#23450;:默?#20064;?#23450;是指在非?#32454;?#27169;式下,且没有使用别的绑定规则时,this根据函数调用(调用栈)的上下文来绑定对象(全局对象)。(?#32454;?#27169;式下则绑定undefined)

        举个栗子:

        function foo() {
          console.log(this.a);
        };
        function bar() {
          var a = 3;
          foo();
        }
        var a = 2;
        bar(); //调用栈在全局作用域,this绑定全局对象
        
        

        运行结果为: 2

        //?#30001;?use strict"运行结果则会变成this is undefined

        这里的函数调用时,使用了默?#20064;?#23450;,函数调用(调用栈)的上下文是全局作用域,因此this绑定了全局对象(global)。

        eg2:

        function foo() {
          console.log(this.a)
        };
        var a = 2;
        (function() {
          "use strict"
          foo();
        })();

        运行结果为: 2

         这里需要注意:对于默?#20064;?#23450;,决定this绑定对象的不是调用位置是否处于?#32454;?#27169;式,而是函数体是否处于?#32454;?#27169;式(函数体处于?#32454;?#27169;式则this绑定undefined;否则this绑定全局对象)。另外:?#32454;?#27169;式和非?#32454;?#27169;式虽然有可能可以绑定,但是最好不混用。

        间接引用一般也是会应用默?#20064;?#23450;规则。

        function foo() {
          console.log(this.a);
        };
        var a = 2;
        var o = { a: 3, foo: foo };
        var p = { a: 4 };
        o.foo();  //3
        (p.foo = o.foo)(); //2

        赋值表达式 p.foo = o.foo的返回值是直接引用目标函数foo。

        二、隐式绑定

        隐式绑定:由上下文对象调用,绑定到上下文对象。

        举个栗子:

        function foo() {
          console.log(this.a);
        };
        var obj = {
          a: 2,
          foo: foo
        };
        obj.foo();  //2
        foo();    //undefined

        这段代码中,foo()被当做引用属性添加到obj对象中,obj调用这个引用属性函数时,会使用该引用属性上下文,this会被绑定到obj对象。(这个函数?#32454;?#26469;说不属于obj对象,只是作为引用属性)。属于隐式绑定。

        而下面foo()函数的直接执行,并不是obj对象引用,所以上下文对象是全局对象。故this绑定了undefined。属于默?#20064;?#23450;。

        对象引用链中只有上一层或者说最后一层在调用位置中起作用。

        注意:

        1.隐式绑定的函数会丢失绑定对象。此时它会应用默?#20064;?#23450;,将this绑定到全局对象或者undefined上,取决于是否是?#32454;?#27169;式。

        eg:

        function foo() {
          console.log(this.a);
        };
        var obj = {
          a: 2;
          foo: foo
        }
        var bar = obj.foo;
        var a = 'biubiubiu';
        bar();

        运行结果:"biubiubiu"

        解析:?#27492;芺ar是obj.foo的一个引用,?#23548;?#19978;bar是直接引用了函数foo,是一个单纯的函数调用,故实为默?#20064;?#23450;。

        2.参数传递就是隐式赋值,因此传入函数时也会被隐式赋值。

        eg:

        function foo() {
          console.log(this.a);
        };
        var obj = {
          a: 2,
          foo: foo
        };
        function bar(fn) {
          fn();
        };
        var a = "biubiubiu";
        bar(obj.foo);
        

        运行结果: "biubiubiu"

        解析:?#23548;?#19978;参数也是隐式赋值,但是参数传入函数中,并在函数中执?#23567;?#27492;时也是直接引用了函数foo,因此也是单纯的函数调用,采用了默?#20064;?#23450;。

        3.把函数传入语言内置函数。(与上面情况基本相似,将自己声明函数改成语言内置函数)回调函数丢失this的情况比较常见,况?#19968;?#26377;调用回调函数的函数可能还会修改this。

        三、显式绑定

        显式绑定:直接将this绑定到指定对象上。Javascript中绝大多数函数和自己所创建的函数都可以使用这两种显式绑定的方法。

        1、.call()
        2、.apply()

        这两种绑定方法,第一个参数是this绑定的对象。(如果传入的参数是原始值(字符串类型、?#32423;?#31867;型、数字类型),这个原始值就会被转成对象形式(new String、new Boolean、new Number)这个称为:装箱)

        举个栗子:

        function foo() {
          console.log(this.a);
        };
        var obj = {
          a: 2
        };
        foo.call(obj);

        运行结果: 2

         然鹅,显示绑定并不能解决绑定丢失的问题。这个时候来了一位新朋友 -- 硬绑定(bind)。

        3、.bind() (硬绑定是常见场景,故es5提供了该内置方法 Function.prototype.bind。)
        bind()会返回一个新编码函数,把this绑定在指定参数上,并调用函数。

        举个栗子:

        function foo(e) {
          console.log(this.a + e);
          return this.a + e;
        };
        var obj = {
          a: 2
        }
        var bar = foo.bind(obj); //新编码函数
        var b = bar(3); // 2 3
        console.log(b); // 5

        bind()还有一个功能?#33322;?#38500;了第一个用于绑定this的参数之外的其他参数传给下层的函数(部分应用,是“柯里化”的一种)。

        这里涉及到一个概念:把null或者undefined作为this的绑定对象传入call、apply、bind,这些值在调用的时候会被忽略,?#23548;?#24212;用默?#20064;?#23450;规则。
        应用场景:

        1. 1、使用apply()展开一个数组,并作为参数传递给一个函数。
        2. 2、bind()对参数进行柯里化(预先设置一些参数)。

        举个栗子:

        function foo(a,b) {
          console.log("a:" + a + ",b:" + b);
        };
        //数组“展开”成参数
        foo.apply(null,[2,3]); //a:2,b:3
        //bind()柯里化
        var bar = foo.bind(null,2);
        bar(3); //a:2,b:3

        解析:传入一个参数作为this绑定对象,如果不传则使用占位符(null),此时会使用默?#20064;?#23450;规则。

        上面这个例子可能会产生一定的副作用,如果需要运用这种场?#23433;?#19988;更加安全。可?#28304;?#24314;一个空对象(可以用?#25105;庀不?#30340;名字来命名)。

        var ∅ = Object.create(null);
        //上面这个例子就可以改写为:
        foo.apply(∅,[2,3]); //a:2,b:3
        var bar = foo.bind(∅,2);
        bar(3); //a:2,b:3

        注意:硬绑定之后不能使用隐式绑定和显式绑定对this进行修改
        在这里介绍一种软绑定的方法softBind(),检查this绑定到全局对象或者undefined后,绑定this到指定的默认对象。绑定后效果和硬绑定一样,但是保留隐式绑定或者显式绑定修改this的能力。

        四、new绑定

        Javascript中的new机制与面向类语言的完全不同。在Javascript中,构造函数只是一些使用new操作符时被调用的函数,不属于一个类,也不会实例化一个类。称为对函数的“构造调用”。

        举个栗子:

        function foo(a) {
          this.a = a;
        }
        var bar = new foo(2);
        console.log(bar.a); //2

        使用new的过程会创建一个全新的对象,this会绑定这个新对象。如果函数没有返回其他对象,则new表达式函数调用会返回该新对象。(这个新对象会连接prototype)

        四种绑定规则的优先级为:new>显式>隐式>默认

        箭头函数

        箭头函数是根据外层作用域(函数或全局)来决定this。(词法作用域取代this机制)
        箭头函数this会绑定调用时的对象,且箭头函数的绑定无法修?#27169;╪ew也不行)。

        其实可以理解为,箭头函数的this在词法上继承的是它所在的作用域(函数或全局)的this,而它继承的函数作用域的this绑定的是在该函数调用上下文对象,所以箭头函数的this间接的绑定在调用上下文对象。

        简述: 箭头函数this(绑定作用域this)-- 作用域this(绑定在调用上下文对象)。

        故:箭头函数this == 调用的上下文对象

        举个栗子:

        function foo() {
          setTimeout(function() {
            //这里的this在词法上继承自foo()
            console.log(this.a);
          },100);
        };
        var obj = { a: 2 };
        foo.call(obj); //2

        其实这个栗子也等价于:

        function foo() {
          var that = this; //lexical capture of this
          setTimeout(function() {
            console.log(self.a)
          },100);
        }
        ...与上面一样

        所以,有两种风格:this风格(四种规则)和词法作用域风格(that = this和箭头函数)可供使用。使用?#26412;?#37327;避免混用,否则会造成难以维护的后果。

        以上所述是小编给大家介绍的Javascript的this的作用详解整合,希望对大家有所帮助,如果大家有任?#25105;?#38382;请给我留言,小编会及时回复大家的。在此也非常?#34892;?#22823;家对脚本之家网站的支持!

        相关文章

        最新评论

        2018白小姐一肖中特马
        <sup id="sjju3"><noscript id="sjju3"></noscript></sup>
        <big id="sjju3"></big>

      2. <blockquote id="sjju3"></blockquote>
        <blockquote id="sjju3"></blockquote>

          <td id="sjju3"></td>

          <big id="sjju3"></big>
            <code id="sjju3"><strong id="sjju3"><dl id="sjju3"></dl></strong></code>
          1. <sup id="sjju3"><noscript id="sjju3"></noscript></sup>
            <big id="sjju3"></big>

          2. <blockquote id="sjju3"></blockquote>
            <blockquote id="sjju3"></blockquote>

              <td id="sjju3"></td>

              <big id="sjju3"></big>
                <code id="sjju3"><strong id="sjju3"><dl id="sjju3"></dl></strong></code>