this 基本概念

2017-04-12  本文已影响10人  南航
  1. 为什么要使用this
  2. this 的使用误解 ( 2 种 指向误解 )
  3. this 和词法作用域的比较
  4. this 的指向正解
  5. this 的绑定方法( call()、apply()、bind() )

this 总是返回一个对象( fun 也是一个对象 ) + this 指向总是善变的

this 的三篇文章按照顺序复习
this基本概念 -> this绑定规则 -> this 应用实例

基本概念

this 总是返回一个对象 即包含当前属性或者方法函数的对象, 因为对象的属性和方法函数可以赋予另一个对象,所有 this 指向的对象也是善变的。

  function foo () {
  console.log('name :' + this.name);
  }

  var obj = { name: "obj1", foo: foo };
  var obj2 = { name: "obj2", foo: foo };
  var obj3 = { name: "obj3" };

  obj.foo()   // obj1
  obj2.foo()    // obj2
  1. 为什么 使用this
  1. this 的使用误解 ( this 的指向误解 )

    1. this 并不指向函数自身

    2. this 不一定指向定义它的函数作用域或者定义时的作用域

       function foo() {
           var a = 2;
           this.bar = function() {
             console.log(this.a)
           }
         this.bar();
       }
       foo();
      
  2. this 和词法作用域的比较

    this 可以通过 参数传递 或者 直接的对象引用来代替。

    ** 但是 this 因为有其更加灵活的特性才被大家所使用,总是使用词法作用域容易让你 回到编程的舒适区 **

我们来记录 foo 函数被调用的次数

    function foo(num) {
        console.log('foo ' + num);

        // 记录 foo 函数被调用的次数
        this.count++;
    }

    foo.count = 0;
    for(var i = 0; i < 5; i++) {
        foo(i);
    }

    // 记录 foo 函数被调用的次数
    console.log(foo.count);

  分析一下上面的 输出 的值 和 this 的指向?
  若需要你来改造 你应该怎么办??
  1. this 的指向正解 ( 请看 this 的 四种绑定策略 )

    函数内部的this 总是指向 函数本身被调用的位置。(this 绑定规则有详解)

    所以对于 this 的 指向就是 寻找函数的调用位置为首。(浏览器自带的 开发者工具可以很方便的查看函数调用栈)

  2. this 的 三种强制绑定的 方法详解

** javascript 提供了 call apply 和 bind 三个方法,用于固定 this 的指向 **

** call 和 apply bind 都是定义在 Function 上面的方法。**
** call apply 返回一个调用函数的执行结果。 **
** bind 返回一个修改了内部this的 包装函数。 **

apply call bind 使用全攻略 ( 4种使用场景 )

  1. 传递空对象 ** 参数柯里化 **( 看你传递的对象到底有多空 )

    call apply bind 传递一个空对象常常用于参数的柯里化

     function bar(a, b) {
           console.log(a + ',' + b);
     }
    

    直接使用 null / undefined 作为空 传入

     var baz = bar.call(null, 1, 4)      // 1, 4
    
     var bak = bar.bind(null, 10);
     bar(19)    // 10,19
    

    传递进去一个 真空对象 var ø = Object.create(null);

    var baz = bar.call(ø, 1, 4)       // 1, 4
    
  2. 自定义的两种 bind 方法

    1. 创建自定义的 bind 方法函数

       function bindCopy(fn, obj) {
             return function() {
                    fn.apply(obj, arguments);            // 这里主要依赖 call 方法 ** 注意不能少了函数参数 **
              }
       }
      
    2. 扩展函数方法库(** 重要知识点 **)

      Function.prototype.bindCopy() {
             var fn = this;
             var obj = arguments[0];
             var args = Array.prototype.slice(arguments, 1);
             return function() {
                      fn.apply(obj, args)
             }
       }
      

      重要知识点:

      • 函数使用 prototype 可以进行扩展( Function.ptototype.bindCopy )

      • 使用 apply 可以将 类数组对象( 有 length 属性的对象 ) 进行参数结构

      • 函数自身调用时也是使用 this 表示调用的上下文

      • 注意 原函数本身的 参数不能少

  3. apply 和 call 的妙用

    1. 将数组解构 (上面是将类数组对象解构)

      var arr = [1, 4, 6, 7];
      Math.max.apply(null, arr);        // 7
      
    2. 使用 call 方法用在 对象继承中 重新调用被子类覆盖的父类方法;

       function Parent() {
           this.a = 'super';
           this.Super = function() {
                  console.log('父类的 Super 方法' + this. a);      
           }
       }
      
       var p = new Parent();
      
      function Children (a) {
            this.a = a;
            Parent.call(this);     // 调用 父类的构造函数
       }
      
      var c = new Children(12);
      c.Super()          // 使用子类 继承过来的方法
      
      c.Super.call(p)        // 使用 call 重新调用父对象的方法
      

    试着自己实现一个类似 于 forEach 的 方法吧

.

上一篇下一篇

猜你喜欢

热点阅读