JavaScript 中的this

this 分享

什么是this?

​ 当一个函数调用时,会创建一个活动记录也就是执行上下文。调用记录包含了,调用栈、传入的参数、函数的调用方法。this 就是这个记录上的一个属性,在函数运行时动态绑定,它的上下文取决于函数调用时的各种条件。和函数申明的位置无关。(取决于调用位置)

this 不是指向函数自身,也不是指向函数的词法作用域。

使用调试工具查看函数调用栈

​ 在函数中第一句使用 debugger,查看调用栈,第二行为当前函数的调用环境。

function fa(){
    debugger;
    console.log("fa");
    fb();
}
function fb(){
    debugger;
    console.log("fb");
    fc();
}

function fc(){
    debugger;
    console.log("fc")
}

this绑定规则

  • 第一种:默认绑定

    默认绑定旨在,函数独立调用时默认绑定this。浏览器环境下为window(注意非严格模式),严格模式下为undefined。优先级是最低的一种绑定方式。

  • 第二种:隐式绑定

    规则:调用位置是否有上下文对象,(函数调用时被某些对象拥有)

    function foo (){
        debugger;
        console.log(this.pro);
    }
    var pro =" global "var obj = {
        pro:"obj",
        foo:foo
    }
    obj.foo()
    
    

    ​ 隐式丢失:当一个对象上的函数被一个无任何修饰的变量保存引用后,隐式绑定规则失效(进而只能使用默认的绑定规则)

    var obj = {
        foo(){
            console.log(this.pro);
        },
        pro:"obj"
    }
    var pro = "global";
    var foo = obj.foo;//function(){console.log(this.pro)}
    foo()
    
    

    ​ 注:通常这种情况发生最多的是回调函数失去 this 。

  • 显示绑定

    在开发中我们通常最喜欢使用这样的方式来,强迫一个对象去贡献一些数据。call/apply 的使用,他们都是显示的将函数绑定到一个对象上来强制改变 this 的指向问题。不同的是它们的参数传递方式的不同。

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

    ​ 显然这也不饿能解决,回调函数失去(活动太改变)this。

    • 硬绑定

      ​ 借助显示绑定的原理,包装一层函数来实现 。

      function foo(){
          console.log(this.pro);
      }
      var obj = {
          pro:"obj"
      }
      var fa = function (obj){
          foo.call(obj);
      }
      
      fa.call(window,obj);//即使这样也能不改变 foo 硬绑定上去的 this 对象
      
      
    • 模仿一下 Function.prototype.bind 函数

      function bind(fn,obj){
          return function (){
              return fn.apply(obj,aguments);
          }
      }
      
      

  • new 绑定

    ​ 构造调用函数时,会有这么一个影响 this的过程,函数首先会在内部创建一个对象=》然后执行原型连接=》将这个对象绑定到函数调用的this 上=》最后在没有返回对象的情况下返回这个对象。

    function Foo(a){
    	this.a =a;	
    }
    let obj = new Foo(22);
    
    console.log(obj.a)// 22
    
    

绑定的优先级

​ 默认绑定是优先级最低的前面有说到, 这儿我们就不讨论它了。

  • 隐式绑定和显示绑定的比较
function foo(){
    console.log(this.pro);
}

var obj1 = {
    pro:"obj1",
    foo:foo
}
var obj2 = {
    pro:"obj2",
    foo:foo
}

obj1.foo();// obj1
obj2.foo();// obj2

obj1.foo.call(obj2);// obj2

​ 显然显示绑定优先级更高,因此我们呢考虑 this 绑定的时候应该先考虑显示绑定。

  • 隐式绑定与 new 的比较

    function foo(a){
        this.a = a;
    }
    var obj={
        foo:foo
    }
    
    obj.foo(2);
    console.log(obj.a);//2
    
    var obj2 = new obj.foo(3);
    console.log(obj2.a);//3
    
    

    ​ 结论:new 的优先级比 隐式高要。

  • 显示绑定与 new 的比较

    ​ 因为call /apply 不能同 new 同时使用,因此我们借用硬绑定(显示绑定的一种)简单直接使用bind函数来实现。

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

    ​ 呀呵!new 的 优先级比显示绑定更高些。因此得出一些结论。

    ​ 优先级:new > 显示绑定 > 隐式绑定 > 默认绑定

特殊的绑定

​ 在实现显示绑定的时候如果传入,null、undefined 作为 call /apply 的第一个参数,那么实际上将使用默认绑定。但是为什么会有这个需求呢?因为柯里化的一种需要使用 bind 来预先传入一些参数(柯里化实际上就是将参数减少)。

foo.bind(null,name,age);

但是会带来默认的绑定,这就可能修改window(全局)的一些属性。有可能这是没有预期的,带来的 bug 很难追踪到。为此需要新建一个 ‘ 假装是空的对象’(不需要Object.prototype 属性),Object.create(null) 来创建一个比{}更空的对象。

1552034074268

绑定误区

​ 眼睛有点闹腾直接看代码吧!

function foo(){
	console.log(this.a)
}
var a = 111;
var obj = {a:222,foo:foo};
var obj1 = {a:333}
(obj1.foo = obj.foo)()//111
foo()//

很软的一种绑定

​ soft bind ,当使用硬绑定后,隐式绑定和显示绑定就无法修改 this 了。因此硬绑定降低了函数的灵活性,与JavaScript 如此灵活(简直想哭)格格不入。如果给默认绑定指定一个除全局对象和undefined外的对象,这就达到了软绑定的需求。(优先级低,但不是全局对象做this)。

if(!Function.prototype.softBind){
    Function.prototype.softBind = function (obj){
        var fn = this;
        var curried = [].slice.call(arguments,1);
        var bound = function (){
            return fn.apply((!this || this === ( window || global))? obj:this
                            ,curried.cancat.apply(curried,arguments)
                           );
        };
        bound.prototype = Object.create(fn.prototype);
        return bound;
    }
}

箭头函数说在最后

​ 箭头函数不受四种绑定规则的约定,它将外部作用域作为this。而且,箭头函数的 this 不被改变(使用优先级最高的new也不行)因为它不使用 new 关键字。改变了 this的机制。具体再举个列:

function foo (){
    setTimeout(()=>{
        console.log(this.a);
    },100)
}
var obj = {a:123};
obj.foo = foo;
var obj1 = {a:456};
obj.foo.bind(obj1);
obj.foo();//123

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蛋白质是生物体普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值