call,apply,bind 方法的學習

這是三個經常使用的操做函數的方法,在js中函數就是一等公民,因此說掌握這三個方法仍是有必要的

 

call 和 apply,都會綁定函數的上下文(context)並當即執行調用該方法函數,二者區別在於,接受的參數格式不同。數組

call 接收的參數形式是: (context,arg1,arg2,ar3....)  // argn 是一個個具體的參數閉包

apply 接收的參數形式是: (context,argArr) // argArr 能夠是一個有參數組成的數組或者argumentsapp

bind 會返回綁定調用該方法的函數上下文的新的函數。函數

 

1.call的示例測試

var a = {
  name: 'aa',
  getName: function(age) {
    return this.name + ',' + age;
  }
};
var b = {
  name: 'bbb'
};

a.getName.call(b,23) // bbb,23

 

1.用call實現applythis

如今的我能想到的辦法就是經過eval對參數進行拼接,由於函數底層操做參數的方法沒有暴露(可能不知道吧)spa

代碼示例prototype

這裏先看下一個eval做用域的事情,通過測試eval方法獲取變量也是在劃分做用域的,並非從全局獲取,示例:code

(function () {
  var me = {name: '33'};
  console.log(eval('me')); // 33
})();

這樣咱們就能拿到函數原來的上下文blog

用call實現apply

// 用個low的辦法實現apply

Function.prototype.fakeApply = function (context,arguments) {
  // 拼接參數
  var arg;

  // 若是有參數將參數轉換成數組
  if(arguments){
    arg = [].slice.call(arguments,0);
    // 將數組拼接成字符串格式 ->  arg1,arg2,arg3,...
    arg = arg.join(',');
  }

  var excuteStr  = 'this.call(context' + (arg ?',' + arg : '' ) + ')'; // this.call(context,2,3,4)

  console.log(eval('this.call(context' + (arguments ?',' +  [].slice.call(arguments,0).join(',') : '' ) + ')'));
  // { name: 44 }
  // { '0': 2, '1': 3, '2': 4 }
  // ok
};
var a = {
  name: 'aa',
  getName: function() {
    console.log(this);
    console.log(arguments);
    return 'ok';
  }
};
a.getName.fakeApply({name:44},[2,3,4]);

爲了加深bind理解,下面是用apply實現bind的示例

 

Function.prototype.fakeBind = function () {
  // bind 有可能會傳入綁定的參數
  var prevFun = this;
  var context = arguments[0];
  var prevArg = arguments.length > 1 ? [].slice.call(arguments,1) : [] ;

  return function () {
    var curArg = [].concat.apply(prevArg,arguments);
    return prevFun.apply(context,curArg);
  };
};
var fun1 = function () {
  console.log(this);
  console.log(arguments);
};

var fun2 = fun1.fakeBind({name: 'aaa'},2,3);
fun2(4,5);

// { name: 'aaa' }
// { '0': 2, '1': 3, '2': 4, '3': 5 }

返回了一個新的函數,函數中的prevFun和preArg 是閉包的變量。

相關文章
相關標籤/搜索