• js中this的绑定


    this是js中的一个关键字,它代表当前作用域的上下文环境,而且随着上下文的改变而动态变化。

    this指当前的上下文环境,在不经意间容易改变:

     1 var info = "This is global info";
     2 var obj = {
     3     info: 'This is local info',
     4     getInfo: getInfo
     5 }
     6 function getInfo() {
     7     console.log(this.info);
     8 }
     9 obj.getInfo()    //This is local info
    10 
    11 getInfo()    //This is global info 当前上下文环境被修改了
    12

    这个例子告诉我们:

    1、同一个函数,调用的方式不同,this的指向就会不同,结果就会不同

    2、对象内部的属性的值为引用类型时,this的指向不会一只绑在原对象上。

    其次,还有不经意间丢失this的情况:

     1 var info = "This is global info";
     2 var obj = {
     3     info: 'This is local info',
     4     getInfo: function getInfo() {
     5         console.log(this.info);
     6 
     7         var getInfo2 = function getInfo2() {
     8             console.log(this.info);
     9         }
    10         getInfo2();
    11     }
    12 }
    13 obj.getInfo();
    14 
    15 //This is local info
    16 //This is global info

    上面代码中,对象obj中定义了一个getInfo方法,方法内又定义了一个新的函数,也希望拿到最外层的该对象的info属性的值,但事与愿违,函数内部的this被错误地指向了window对象,这就导致了错误。

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

    this的绑定一共有四种绑定:1、默认绑定(即没有明确的调用对象)

                                                 2、隐性绑定(即作为对象方法调用,this会被绑定到该对象)

                                                 3、显性绑定(使用call()、apply()调用,两个方法的第一个参数为一个对象,this被绑定到该对象)

                                                 4、new绑定(使用new来调用函数,会构造一个对象,并把this绑定到该对象)

    一、默认绑定(即没有明确的调用对象)

    1 function foo(){
    2     var a = 1 ;
    3     alert(this.a);
    4 }
    5 var a = 2;
    6 foo();   //  2    (非严格模式下)

    上面代码中,foo是在全局环境被调用的,所以this被绑定到window。但前提是非严格模式下,如果在严格模式下,this被绑定到undefined。

    二、隐性绑定(即作为对象方法调用,this会被绑定到该对象)

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

    上面代码中,obj对象调用foo函数,因此this被绑定到obj。

    对象属性引用链中只有最后一层会影响调用位置。

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

    上面代码中,obj1和obj2两个对象连续调用,this会被绑定到最后一个对象,即obj2,所以输出2

    三、显性绑定(使用call()、apply()调用,两个方法的第一个参数为一个对象,this被绑定到该对象)

    1 function  foo(){
    2       alert(this.a);
    3 }
    4 var  obj = {
    5        a:1
    6 };
    7 foo.call(obj);  //  1

    call方法的参数若为空,默认调用window对象

           硬绑定——显示绑定的一种变形

                     优点:可以解决丢失绑定问题

                     缺点:硬绑定后不能再修改它的this

     1 function  foo(){
     2      alert(this.a);
     3 }
     4 var obj = {
     5      a:2
     6 };
     7 var  bar = function(){
     8       foo.call(obj);
     9 };
    10 bar();   // 2
    11 setTimeout(bar,100);  // 2
    12 bar.call(window);  // 2

    ES5中提供了内置方法Function.prototype.bind

     1 function foo(something){
     2       alert(this.a, something);
     3       return  this.a + something;
     4 }
     5 var obj = {
     6     a:2
     7 };
     8 var  bar = foo.bind(obj);
     9 var  b = bar(3);   //  2  3
    10 alert(b);   // 5

    bind()会返回一个硬编码的新函数,它会把参数设置为this的上下文并调用原始函数

    四、new绑定(使用new来调用函数,会构造一个对象,并把this绑定到该对象)

    1 function   foo(a){
    2       this.a = a;
    3 }
    4 var bar = new foo(2);
    5 alert(bar.a);  // 2

    上面代码中,bar对象是由foo函数创建得,因此继承了foo函数的属性和方法。

    综上,this绑定的优先级为:new绑定  >  显示绑定  >  隐式绑定  >  默认绑定

    前端面试中经常会问到一个问题:new操作符都干了些什么,回答的时候可以回答一下几点:

    1、创建了一个空对象,并用this引用该对象,同时还继承了该函数的原型

    2、属性和方法被载入到该函数的原型中

    3、新创建的对象由this引用,并且最后隐式地返回this

    1 var obj  = {};
    2 obj.__proto__ = Base.prototype;
    3 Base.call(obj);
  • 相关阅读:
    Firebase 如何创建登录 Token
    GitHub 如何从特定的版本中创建分支
    Firebase 命令行工具
    Python 日期格式和时间以及当前时间和时间戳
    Python DataTime 日期处理
    Python With 关键字和语句
    完整的微信接口类
    HashMap
    java运行时数据区域
    POI学习
  • 原文地址:https://www.cnblogs.com/endlessmy/p/8576096.html
Copyright © 2020-2023  润新知