前面我们学习了改变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课程" ,一个值得推荐的"渡一教育"。