理解js中的this、apply、call、new、bind等方法

  学习js,需要将多个知识点结合起来看,因为js中很多特点或技巧都是有几个基本的属性和方法组合而来的,就比如本文中的new和bind(),其实就是由this+call() | apply() (等同于)组合而来的。下面进入正题:

一、this  

function wrap(){
    f();  //1
    var ff = new f();  //2
    function f(){
        console.log(this);
    };
    
    var o = {
        p:function(){console.log(this);},
    q:function(){
            r();
          function r(){console.log(this);}
    } 
    };  
    o.p();  //3
    o.q();  //4

    var g = function(){
        console.log(this)
    };
    g();  //5 

    //6
    (function(){ 
        console.log(this);
    }());  
}
wrap();

 

 

由此可以看出,this指向的是一个对象字面量。( 虽然函数也是一种特殊的对象,但它的存在的意义是执行操作,而对象字面量则仅限于对某一类东西进行描述。)

判断js中this的指向问题,可以这样:找到被调用的位置,如果是对象的属性,那么this就指向该对象;如果是在函数内部,或者在全局环境下,那么this指向的是window对象;apply()、call()、bind()另算

【注:在严格模式下,未指定环境对象而调用函数,并且没有使用apply()或call(),那么this值为undefined】

 

二、js中能够修改this的方法有两种 : apply() , call() ;

  1. apply() :

         x.apply(this,arguments)   【将后者数组中的元素一个个添加到前面的对象中,这里就是将当前函数的参数全部添加到this中】

           x.apply(this,[arr1,arr2]);  

 

      {

           应用技巧:

         1、数组的添加

var arr1 = [12 , "foo" , {name "Joe"} , -2458];
var arry2 = ["Doe" , 100];
Array.prototype.push.apply(arr1, arr2);   //此时的arr1 值为  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 100]
 
【注:concat方法也能连接数组,但它是创建了一个arr1的副本,原数组不变】
 
2、获取数组中的最大值和最小值
var  num = [5, 458 , 120 , -215 ];
var maxNum = Math.max.apply(Math, num),   //458
maxNum = Math.max.call(Math,5, 458 , 120 , -215); //458
 

      }

 

  2. call() :

      x.call(this,arr1,arr2,arr3);  【必须明确的传入每一个参数】

 

 

   apply和call还可以利用对象和方法之间没有任何耦合关系的这一特征,来实现作用域的切换。

  【关于apply()和call()方法,有篇文章解释的很详细:点击这里  】

 

三、在方法apply()和call()的基础上,还能实现其它的功能,比如new、bind() 方法:

 

new:

var obj  = {};

obj.__proto__ = Base.prototype;

Base.call(obj);

 

  bind():

Function.prototype.bind = function(){ 
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); 
  return function(){ 
    return fn.apply(object, 
    args.concat(Array.prototype.slice.call(arguments))); 
  }; 
}; 

  【call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数】

四、构造函数(this的具体应用)

  构造函数的过程中也会应用到this,所谓构造函数,实际上就是创建了一个新的对象,然后把所有属性和操作在这新的环境下执行。

  在实际执行过程中一般分为两种,一种是先给函数中的属性赋值,然后用new方法实现:

function test(){
   this.a=10;
   return function(){
      return 1;  // do something
   }
}
var m=new test();

  另一种是类似jQuery,把new方法写在函数中:

  (让人惊叹的是jQuery中的构造的方式是可以链式编程的,原理其实相当于用一个新的函数对象(即构造函数对象)替换之,而公共的prototype部分不变。)

z = function() {
  return new z.fn.init();
};
z.fn=z.prototype = {
  constructor: z,
  init:function() {
    return this;
  }
}

 

  【  

    补充总结:

      1、this一旦确定,便无法修改,在函数内会报错

      2、this代表了调用者对象的作用范围,这样就可以通过this来给被调用的对象添加或修改属性

      3、基于2,apply和call方法则是相当于导入了当前作用域相对应的对象

  】

posted @ 2017-08-24 10:33  烽花血月  阅读(325)  评论(0编辑  收藏  举报