zoukankan      html  css  js  c++  java
  • this

    this到底是什么?

    this是在运行时绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

    当一个函数被调用时,会创建一个记录(有时候也称为执行上下文)。这个记录会包含函数函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this就是记录的其中一个属性,会在函数执行的过程中用到。

    如果不使用this,那就需要显示传入一个上下文对象,this提供了一种更优雅的方式来隐式“传递”一个对象的引用。

    仅仅是因为无法猜对this的用法,就放弃学习this而去使用词法作用域,就不能算是一种很好的解决办法。

    声明在全局作用域中的变量就是全局对象的一个同名属性。它们本质上就是同一个东西,并不是通过复制得到的。

    this的绑定规则完全取决于调用位置。注:只有在non-strict mode下时,默认绑定才能绑定到全局对象。

    隐式丢失

    一个最常见的this绑定问题就是被隐式绑定的函数会丢失绑定对象,也就是说它会应用默认绑定,从而把this绑定到全局对象或者undefined上,取决于是否是严格模式。

    显示绑定

    call(...)和apply(...)方法,它们的第一个参数是一个对象,它们会把这个对象绑定到this,接着在调用函数时指定这个this。

    如果你传入了一个原始值(字符串类型、布尔类型或者数字类型)来当做this的绑定对象,这个原始值会被转换成它的对象形式(也就是new String()...)。这通常被称为装箱。

    由于硬绑定是一种非常常用的模式,所以在es5中提供了内置的方法Function.prototype.bind。

    function foo(sth){
        return this.a + sth
    }
    
    function bind(fn,obj){
        return function(){
            return fn.apply(obj,arguments)
        }
    }
    
    var obj = {
        a:'zjy'
    }
    
    var bar = bind(foo,obj)
    var b = bar(' work hard')
    console.log(b)
    

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

    判断this

    • 函数是否在new中调用?如果是的话,this绑定的是新创建的对象。
    • 判断函数是否通过call、apply或者硬绑定调用?如果是的话,this绑定的是指定的对象。
    • 函数是否在某个上下文对象中调用?如果是的话,this绑定的是那个上下文对象。
    • 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到全局对象。

    被忽略的this 

    如果把null或者undefined作为this的绑定对象传入call、apply或者bind,这些值在调用时会被忽略,实际应用的是默认绑定规则。

    软绑定

    硬绑定这种方式可以把this强制绑定到指定的对象(除了使用new时),防止函数调用应用默认绑定规则。问题在于,硬绑定会大大降低函数的灵活性,使用硬绑定之后就无法使用隐式绑定或者显示绑定来修改this。

    如果可以给默认绑定指定一个全局对象和undefined以外的值,那就可以实现和硬绑定相同的效果,同时保留隐式绑定或者显示绑定修改this的能力。

    意思就是说:使用硬绑定之后就无法使用隐式绑定或者显示绑定来修改this,那么就不使用硬绑定,实现一个软绑定(softBind),其功能就是给默认绑定指定一个全局对象和undefined以外的值,那就可以实现和硬绑定相同的效果,同时保留隐式绑定或者显示绑定修改this的能力。

    通过软绑定,我们希望this在默认情况下不再指向全局对象(非严格模式)或 undefined (严格模式),而是指向两者之外的一个对象(这点和硬绑定的效果相同),但是同时又保留了隐式绑定和显式绑定在之后可以修改this指向的能力。
    function createSoftBind(){
        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.concat.apply(curried,arguments)
                    );
                }
                bound.prototype = Object.create(fn.prototype)
                return bound
            }
        }
        return Function.prototype.softBind
    }

    箭头函数并不是使用function关键字定义的,而是使用被称为”胖箭头“的操作符 => 定义的。箭头函数不适用this的四种标准规则,而是根据外层(函数或者全局)作用域来决定this。

  • 相关阅读:
    ios开发 <AppName>-Prefix.pch文件的用法详解
    iOS Block全面分析
    _weak typeof(self) weakSelf = self
    判断当前iOS设备的方法
    修改UITextfield的Placeholder字体的颜色
    uibutton实现左文字右图片
    apache Apache winnt_accept: Asynchronous AcceptEx failed 错误的解决
    android4.0 锁屏实现(转)
    android 代码设置、打开wifi热点及热点的连接(转)
    tomcat arp
  • 原文地址:https://www.cnblogs.com/zhenjianyu/p/13193143.html
Copyright © 2011-2022 走看看