javaSript基础--this

180 阅读4分钟

this

this 是什么

  • 如果来描述 this 的话:

    • 当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。

      • 我理解为 this 的 origin 实则是 this 如何生成(函数调用调用时(this 的指向完全取决于在哪里被调用并不是指向函数自身)),this 的生成必须有个父亲就是上文所说的函数(this 绑定的函数),然而函数则是 this 的关键,调用时间地点也很重要
    • 这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。

      • 我理解为 this 的 myself this 自身的一些信息(调用栈,父亲的方法,函数的参数)
    • this 就是记录的其中一个属性,会在函数执行的过程中用到。

      • 我理解为 this 的 effect this 就是这个记录中的属性,this 使用的地方

为什么用 this

  • this 提供了一种更优雅的方式来隐式“传递”一个对象引用,因此可以将 API 设计 得更加简洁并且易于复用。(说白了就是可以偷懒)使用时需要注意 this 的指向,尤其是回调函数中
function aa(ctx){
  console.log(ctx.name)
}
function bb (){
 console.log(this.name)
}
var ctx={name:"marco is dashuaibi"}
aa(ctx)
aa.call(ctx)

怎么用 this(解析)

怎么使用 this 呢,首先要先问自己 this 到底引用的是什么,也就是上文所说的父亲是谁,父亲在哪里造出的你(函数被调用的位置)

  • 默认绑定(独立函数调用)。 this 是指向 window 的,如果在严格模式下(strict mode),this 则为 undefined

  • 隐式绑定

    function foo() { console.log( this.a ); }
    var obj = { a: 2, foo: foo };
    obj.foo(); // 2
    
    
    • 隐式丢失(被隐式绑定的函数会丢失绑定对象,从而把 this 绑定到全局对象或者 undefined 上)
  • 显式绑定(这里就不讲解这两个方法了,会把对照的 polyfill 写下来)

    • call

      call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数 语法:function.call(thisArg, arg1, arg2, ...)

    Function.prototype.myCall = function(thisArg, ...args) {
      const fn = Symbol('fn')        // 声明一个独有的Symbol属性, 防止fn覆盖已有属性
      thisArg = thisArg || window    // 若没有传入this, 默认绑定window对象
      thisArg[fn] = this              // this指向调用call的对象,即我们要改变this指向的函数
      const result = thisArg[fn](...args)  // 执行当前函数
      delete thisArg[fn]              // 删除我们声明的fn属性
      return result                  // 返回函数执行结果
    }
    
    • apply

      apply() 方法调用一个具有给定 this 值的函数,以及作为一个数组(或类似数组对象)提供的参数。 语法:func.apply(thisArg, [argsArray])

    Function.prototype.myApply = function(thisArg, args) {
      const fn = Symbol('fn')        // 声明一个独有的Symbol属性, 防止fn覆盖已有属性
      thisArg = thisArg || window    // 若没有传入this, 默认绑定window对象
      thisArg[fn] = this             // this指向调用call的对象,即我们要改变this指向的函数
      const result = thisArg[fn](...args)  // 执行当前函数
      delete thisArg[fn]              // 删除我们声明的fn属性
      return result                  // 返回函数执行结果
    }
    

    这两种方法我的理解就很像某鹅厂 这个游戏我做不了,我买下了也是我的(个人拙见)

          - 硬绑定(bind)显示绑定的一种变形
          > bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。语法: function.bind(thisArg, arg1, arg2, ...)常常用于柯里化
          ```
          是 MDN 提供的polyfill
          if (!Function.prototype.bind) {
             Function.prototype.bind = function(oThis) {
              if (typeof this !== "function") {
                throw new TypeError(
                  "Function.prototype.bind - what is trying " + "to be bound is not callable"
                );
              }
              var aArgs = Array.prototype.slice.call( arguments, 1 ),
              fToBind = this,
              fNOP = function(){},
              fBound = function(){
                return fToBind.apply( (
                this instanceof fNOP && oThis ? this : oThis
                ),
                aArgs.concat( Array.prototype.slice.call( arguments ) );
              } ;
              fNOP.prototype = this.prototype; fBound.prototype = new fNOP();
               return fBound;
            };
          }
          ```
          - new 绑定
            1. 创建(或者说构造)一个全新的对象。
            2. 这个新对象会被执行 [[ 原型 ]] 连接。
            3. 这个新对象会绑定到函数调用的 this。
            4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。
          ```
          function foo(a) {
            this.a = a;
          }
          var bar = new foo(2);
          console.log( bar.a ); // 2
          ```
    

    优先级: bind > new > 隐式

软绑定 (以实现和硬绑定相 同的效果,同时保留隐式绑定或者显式绑定修改 this 的能力。) softBind()

polyfill
if (!Function.prototype.softBind) {
  Function.prototype.softBind = function(obj) {
    var fn = this; // 捕获所有 curried 参数
    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;
    };
  }
  • 对了还有一个最重要的 箭头函数的 this,箭头函数没有 this,箭头函数是根据外层(函数或者全局)作用域来决定 this,不能够使用应绑定.
  • 箭头函数式没有prototype的,所以他的this在箭头函数被创建的时候就继承了外层的