前面我們學習了改變this指向的兩個方法:call、apply
下面要隆重介紹第三種改變this指向的方法 ——bind
首先我們通過非常簡單的一小段代碼看一下bind的基本使用:
var x = 10;
function show(){
console.log(this.x);//10 20
}
show();
var aO = {
x: 20
}
var newShow = show.bind(aO);
newShow();
還可以傳入參數
var x = 10;
function show(a, b){
console.log(this.x, a, b);//10 'a' 'b' 20 'c' 'd'
}
show('a', 'b');
var aO = {
x: 20
}
var newShow = show.bind(aO, 'c', 'd');
newShow();
//var newShow = show.bind(aO, 'c');
//newShow('d');
除此之外,在單對象編程的過程中,bind發揮了重大的作用:需求如下,在頁面中有一個button按鈕,在點擊button時,打印相應信息。
var list = {
init : function(){
//this -> list
this.ms = 'duyi';
this.dom = document.getElementsByTagName('button')[0];//此處獲取一個button元素
this.bindEvent();
},
bindEvent : function(){
//this -> list
this.dom.onclick = this.showMessage.bind(this, 'hello', 'world');
},
showMessage : function(info1, info2, e){
//不改變this指向的話,this -> dom,而dom中並沒有ms
console.log(this.ms, info1, info2, e);//duyi hello world 事件對象
}
}
list.init();
下面我們來總結一下bind的使用方法:
function A(){}
var obj = {};
var x = 1;
var y = 2;
var z = 3;
var B = A.bind(obj, x, y);
B(z);
//new B().constructor -> A
1.函數A調用bind方法時,需要傳遞參數obj,xy...
2.會返回新的函數B
3.函數B在執行時,具體功能還是使用的A,但this指向了obj
4.函數B在執行時,傳遞的參數會拼接到xy..後面,一併在內部傳遞給A執行
5.new B(), 構造函數依舊是A,而且obj不會起到任何作用
那麼bind在內部到底是如何來實現的呢?請看如下代碼:
Function.prototype.newBind = function(target){
//target改變返回函數執行的this指向
var self = this;//誰調用的newBind,this就是誰
var args = [].slice.call(arguments, 1);
var temp = function(){};
var f = function(){
//真正執行的self的功能
//new f()
var _arg = [].slice.call(arguments, 0);
return self.apply(this instanceof temp ? this : (target || window), args.concat(_arg));
}
temp.prototype = self.prototype;
f.prototype = new temp();
return f;
}
在後續要學到的jQuery中,實現了類似bind的方法$.proxy(),簡單瞭解一下
var name = 'Lebron';
function show(){
console.log(this);//James
}
var obj = {
name: 'James',
age: 123
}
var showProxy = $.proxy(show, obj);//並沒有改變原來show的this,而是生成一個新的方法
showProxy();
var list = {
init : function(){
//this -> list
this.mes = 123;
this.dom = document.getElementById('demo');
this.bindEvent();
},
bindEvent : function(){
//this -> list
this.dom.onclick = $.proxy(this.show, this);//改變this指向
},
show : function(){
//不改變的話,this -> dom,去找調用它的地方找問題!!!
console.log(this.produceMes(this.mes));
},
produceMes : function(mes){
return mes + 234;
}
}
list.init();
以上內容屬二哥原創,整理自 "渡一教育Javascript課程" ,一個值得推薦的"渡一教育"。