call()、apply()、bind()

Function.prototype.call()

call() 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法.

fun.call(thisArg[, arg1[, arg2[, ...]]])
  • 参数

    • thisArg
      • 在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。
    • arg1, arg2, ...
      • 指定的参数列表。
  • 返回值

    • 返回结果包括制定的this值和参数。
  • 描述

    • 可以让call()中的对象调用当前对象所拥有的function。你可以使用call()来实现继承:写一个方法,然后让另外一个新的对象来继承它(而不是在新对象中再写一次这个方法)。
function Product(name, price) {
  this.name = name;
  this.price = price;

  if (price < 0) {
    throw RangeError('Cannot create product ' +
                      this.name + ' with a negative price');
  }
}

function Food(name, price) {
  Product.call(this, name, price); 
  this.category = 'food';
}

//等同于
function Food(name, price) { 
    this.name = name;
    this.price = price;
    if (price < 0) {
        throw RangeError('Cannot create product ' +
                this.name + ' with a negative price');
    }

    this.category = 'food'; 
}

//function Toy 同上
function Toy(name, price) {
  Product.call(this, name, price);
  this.category = 'toy';
}

var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);

Function.prototype.apply()

apply() 方法在指定 this 值和参数(参数以数组或类数组对象的形式存在)的情况下调用某个函数。

fun.apply(thisArg[, argsArray])
  • 参数
    • thisArg
      • 在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。
    • argsArray
      • 一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。
  • 描述
    • 在调用一个存在的函数时,你可以为其指定一个 this 对象。 this 指当前对象,也就是正在调用这个函数的对象。 使用 apply, 你可以只写一次这个方法然后在另一个对象中继承它,而不用在新对象中重复写该方法。
Function.prototype.construct = function (aArgs) {
  var oNew = Object.create(this.prototype);
  this.apply(oNew, aArgs);
  return oNew;
};

// 在全局Function上添加一个方法,对所有Function有效
// this 指向调用方法的对象
// oNew是以这个对象的原型为原型构造出来的新对象,
// this.apply(oNew,aArgs) 调用this指向的函数对象,并把这个函数对象的this直线oNew,以aArgs里的成员作为函数的参数
// 这个方法返回这个新对象

function MyConstructor () {
    for (var nProp = 0; nProp < arguments.length; nProp++) {
        this["property" + nProp] = arguments[nProp];
    }
}

// 声明一个构造函数,并解析传入的参数

var myArray = [4, "Hello world!", false];
var myInstance = MyConstructor.construct(myArray);
// 调用构造函数的construct()方法
// 这个方法首先以这个函数为原型构造一个新对象oNew
// 再以oNew作为this指向,myArray里的元素作为参数调用这个函数
// 运行结果oNew {property0: 4, property1: "Hello world!", property2: false}
// 把这个对象返回,赋值给myInstance

Function.prototype.bind()

bind()方法会创建一个新函数,当这个新函数被调用时,它的this值是传递给bind()的第一个参数, 它的参数是bind()的其他参数和其原本的参数.

fun.bind(thisArg[, arg1[, arg2[, ...]]])

参数

  • thisArg

    • 当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new 操作符调用绑定函数时,该参数无效。
  • arg1, arg2, ...

    • 当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数。
  • 返回值

    • 返回由指定的this值和初始化参数改造的原函数拷贝
  • 描述

    • bind() 函数会创建一个新函数(称为绑定函数),新函数与被调函数(绑定函数的目标函数)具有相同的函数体(在 ECMAScript 5 规范中内置的call属性)。当目标函数被调用时 this 值绑定到 bind() 的第一个参数,该参数不能被重写。绑定函数被调用时,bind() 也接受预设的参数提供给原函数。一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。

bind 兼容写法

if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable 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 ? this : oThis || this,
            //this指向函数的调用者,当函数普通调用时,this指向 oThis || this
            //作为构造函数调用时 this指向构造出来的新对象
            //新对象的原型指向fNOP的实例
            //fNOP的实例的原型又指向绑定函数的原型
            //使用绑定后函数构造出来的新对象的原型也指向绑定函数的原型
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;// 把fNOP的原型指向绑定的函数
    fBound.prototype = new fNOP(); //把fBound的原型指向fNOP构造出来的新对象 
         //fBound的原型被指定为new fNOP(),
          //也就是说如果我们绑定了一个构造函数A得到新的构造函数B,则使用B构造的对象仍然会是A的实例,只不过原型链被new fNOP插了一脚
        //反正new fNOP()本身是{}没有什么属性,插这一脚不影响新对象的使用
    return fBound;
  };
}

// 简单写法
if(!Function.prototype.bind){
    Function.prototype.bind = function (obj) {
        var arr = Array.prototype.slice.call(arguments,1),
            _self=this,
            return function(){
                _self.apply(obj,arr.concat(Array.prototype.silce.call(arguments)));
            }
    }
}

你可能感兴趣的:(call()、apply()、bind())