zoukankan      html  css  js  c++  java
  • 2.2 .this的绑定规则

    2.this的绑定规则

    1.默认绑定

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

    在代码中,foo()函数不带任何修饰的引用进行调用的,那么只能使用默认绑定。


    2.隐式绑定

    1 function foo1()
    2 {
    3    console.log( this.a );
    4 }
    5 var obj = {
    6    a: 1,
    7    foo: foo1
    8 };
    9 obj.foo();  //1


    调用位置使用obj上下文来引用函数foo2,故可以说函数被调用时obj对象“拥有”或“包含”该函数foo2()。
    那么foo2函数被调用时,确实加上了对obj的引用。当函数引用有上下文对象时,
    隐式绑定规则会把函数调用中的this绑定到这个上下文对象。
    故上文中的this.a等同于obj.a。


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

     1 function foo2()
     2 {
     3    console.log( this.a );
     4 }
     5 var obj2 = {
     6    a: 2,
     7    foo: foo2
     8 };
     9 var obj1 = {
    10    a: 3,
    11    obj2: obj2
    12 };
    13 obj1.obj2.foo();    //2


    距离this最近的对象上下文时obj2,故this.a等同与obj2.a,同时等同于obj1.obj2.a。


    PS2:隐式丢失

     1 function foo3()
     2 {
     3    console.log( this.a );
     4 }
     5 var obj3 = {
     6    a: 33,
     7    foo: foo3
     8 };
     9 var bar=obj3.foo;
    10 var a=3;
    11 bar();  //3


    这里的要点就是关注var bar=obj3.foo;
    虽然bar只是obj3.foo的一个引用,但bar实际引用的时foo3()函数本身。
    因此此时的bar()其实是一个不带任何修饰的函数调用,所以应用默认绑定。


    PS2:隐式丢失(发生在函数调用时)。

     1 function foo4(  )
     2 {
     3    console.log(this.b);
     4 }
     5 function doFOO( fn )
     6 {
     7    var b=44;
     8    fn();
     9 }
    10 var obj4={
    11    b:10,
    12    foo:foo4
    13 };
    14 var b=4;
    15 doFOO(obj4.foo);    //4


    参数传递其实就是一个隐式赋值,故传入函数也会被隐式赋值。
    所以结果与上面例子一致。
    同理,这里传入的是自定义函数。即使传入的是内置函数,结果也是一样的。


    PS3:如上所见,回调函数丢失this绑定是很常见的。
    与此同时,另一种丢失情况更加出人意料:调用回调函数可能会修改this。
    在一些流行的js库中,事件处理器经常会把回调函数的this绑定到DOM元素上。



    3.显式绑定
    显式绑定,即是通过call,apply等方法来强制绑定。
    call与apply的第一个参数都是thisObj,表示this的指向。第二个参数,call是输入单个参数,apply是输入参数数组。多个参数时,后者性能更优。

    1 function foo()
    2 {
    3    console.log( this.a );
    4 }
    5 var obj = {
    6    a: 3
    7 };
    8 foo.call( obj );   //2     函数没有参数输入时,call只需要一个参数thisObj输入。


    通过foo.call(),可以在调用foo时强制把它的this绑定到obj上。

    PS1:“装箱”
    如果thisObj参数传入的是一个原始值(简单数据类型),这个原始值会被转换成它的对象形式(如new String(..),new Boolean(..),或者new Number(..))。这通常称为“装箱”。

    PS2:解决之前提出的丢失绑定问题。
    1.硬绑定(显式绑定的一个变种)

     1 function foo2()
     2 {
     3    console.log( this.a );
     4 }
     5 var obj2 = {
     6    a: 3
     7 };
     8 var bar = function()
     9 {
    10    foo2.call( obj );
    11 };
    12 bar();  //3
    13 setTimeout( bar, 100 ); //3
    14 
    15 //切记,硬绑定的bar不可能在修改它的this。
    16 bar.call( window );   //3


    硬绑定的典型应用场景就是创建一个包裹函数,负责接收参数并返回值;
    另一个使用方法就是创建一个可以重复应用的辅助函数:

     1 function foo3( something )
     2 {
     3    console.log( this.d, something );
     4    return this.d + something;
     5 }
     6 function bind( fn, obj )
     7 {
     8    return function()
     9    {
    10       return fn.apply( obj, arguments );
    11    };
    12 }
    13 var obj3 = {
    14    d: 2
    15 };
    16 var bar3 = bind( foo3, obj3 );
    17 var e = bar3( 3 );  //2 3
    18 console.log( e ); //5


    由于硬绑定是一个非常常用的模式,故ES5提供了一个内置方法bind,和上述用法类似。

     1 function foo4( something )
     2 {
     3    console.log( this.a4, something );
     4    return this.a4 + something;
     5 }
     6 var obj4 = {
     7    a4: 2
     8 };
     9 var bar4 = foo4.bind( obj4 );
    10 var b4 = bar4( 5 ); //2 5
    11 console.log( b4 );    //7


    bind(..)会返回一个硬编码的新函数(切记,新函数),这会将指定的参数设置为this的上下文并调用原始函数。

    2.API调用的“上下文”
    第三方库的许多函数,以及JS语言和宿主环境(如浏览器环境)中许多内置函数,都提供了一个可选参数,通常称为“上下文(context)。
    其作用与bind(..)类似,确保回调函数使用指定的this。

     1 function foo5( el )
     2 {
     3    console.log( el, this.id );
     4 }
     5 var obj5 = {
     6    id: "awesome"
     7 };
     8 
     9 //调用foo5(..)函数是将this绑定到obj。
    10 [ "1", 2, 3 ].forEach( foo5, obj5 );    //console.log输出数字和字符串时,数字在前,字符串会有双引号;反之则没有。
    11 // 1 awesome; 2 awesome; 3 awesome

    4.new绑定
    在此先纠正js中new与其他语言中new的区别。
    在其它面向类语言中,”构造函数“是类中的一些特殊方法,使用new 初始化类时调用类中的构造函数。
    在JS中,构造函数只是一些使用new操作符时被调用的函数。它们不属于某个类,也不会实例化一个类。

    JS中使用new来调用函数,或者说发生构造函数调用时,会自动执行以下操作。
      1.创建(或者说构造)一个全新的对象。
      2.这个新对象会被执行[[Prototype]]链接。
      3.这个新对象会绑定到函数调用的this。
      4.如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。

    1 function foo( a )
    2 {
    3    this.a = a;
    4 }
    5 var bar = new foo( 4 );
    6 console.log( bar.a );
    7 
    8 //使用new来调用foo(..)时,会构建一个新对象并将它绑定到foo(..)调用的this上,并将该对象返回给bar。






  • 相关阅读:
    sqlhelper使用指南
    大三学长带我学习JAVA。作业1. 第1讲.Java.SE入门、JDK的下载与安装、第一个Java程序、Java程序的编译与执行 大三学长带我学习JAVA。作业1.
    pku1201 Intervals
    hdu 1364 king
    pku 3268 Silver Cow Party
    pku 3169 Layout
    hdu 2680 Choose the best route
    hdu 2983
    pku 1716 Integer Intervals
    pku 2387 Til the Cows Come Home
  • 原文地址:https://www.cnblogs.com/Tiancheng-Duan/p/8296908.html
Copyright © 2011-2022 走看看