call()、apply()、bind()

2016-11-24  本文已影响0人  angelwgh

Function.prototype.call()

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

fun.call(thisArg[, arg1[, arg2[, ...]]])
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])
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[, ...]]])

参数

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)));
            }
    }
}

上一篇下一篇

猜你喜欢

热点阅读