函数bind的实现
来源:互联网 发布:淘宝申请售后时间 编辑:程序博客网 时间:2024/06/05 20:33
最近在看《MVC的JavaScript Web富应用开发》,其中出现了ES5新增的bind函数的实现代码,本人菜鸟一枚,花了一天才搞明白,代码先上:
if (!Function.prototype.bind) { Function.prototype.bind = function (obj) { var slice = [].slice, args = slice.call(arguments, 1), self = this, nop = function () {}, bound = function () { return self.apply( this instanceof nop ? this : (obj || {}), args.concat(slice.call(arguments))); }; nop.prototype = self.prototype; bound.prototype = new nop(); return bound; };}
本文假设读者水平和我差不多,一步一步进行分析,高手勿喷,如果可以帮我解答一下最后的疑问,thx。
开始实现这个函数
根据bind返回的函数的作用的不同,这个函数有两种情况:(1)做普通函数(2)做构造函数
当新函数是普通函数时,代码为:
Function.prototype.bind = function (obj) { var slice = [].slice, args = slice.call(arguments, 1), self = this, bound = function () { return self.apply( obj || {}, args.concat(slice.call(arguments))); }; return bound;};
代码中:
[].slice.call(arguments, 1) 或者 Array.prototype.slice.call(argumens, 1)
因为arguments不是真的数组,不能改变,所以通过[].slice.call(arguments)来返回参数数组。
args.concat(slice.call(arguments))
把两个参数数组整合到一起
另外,代码中 return bound; 涉及到闭包(或者函数柯里化),这里不展开,如果闭包的概念不知道可以搜索一下,面试经常问到。
当新函数用作构造函数时,上面的代码就不适用了,如下:
var Book = function(name, price){ this.name = name; this.price = price;};var NoteBook = Book.bind(null ,'notebook'), n = new NoteBook(13);console.log(n) // 实际:{}, 预期:{name: 'notebook', price: 13}
说明上面的代码需要完善,在这之前,我们先了解一下函数用new的实际过程(《JavaScript高程序设计》P145)
1.创建一个新对象
2.将构造函数的作用域赋给了this对象(因此this指向这个新对象)
3.执行构造函数中的代码
4.如果没有return,自动返回this,否则返回你返回的对象
现在解释为什么会返回 {}:
通过上面的步骤,我们可以知道关键就是self.apply调用时传入的对象不是实例对象,所以改变它就好了。
所以将obj || {}改成:this instanceof bound ? this : (obj || {}),这样就可以顺利返回实例,同时在执行Book函数时能保证this指向该实例,代码变成:
Function.prototype.bind = function (obj) { var slice = [].slice, args = slice.call(arguments, 1), self = this, bound = function () { return self.apply( this instanceof bound ? this : (obj || {}), args.concat(slice.call(arguments))); }; return bound;};
到这里解决了一些问题,但是还不够,不要忘记了,我们在Book的原型上可能定义了一下方法或者属性。
......Book.prototype.say = function(){ console.log(this.name);};......
以上代码可没有办法做到继承到Book原型上的方法,所以应该bound应该继承Book的原型方法
Function.prototype.bind = function (obj) { var slice = [].slice, args = slice.call(arguments, 1), self = this, nop = function () {}, bound = function () { return self.apply( this instanceof bound ? this : (obj || {}), args.concat(slice.call(arguments))); }; nop.prototype = self.prototype; bound.prototype = new nop(); return bound;};
到此和书上代码就基本一样了,除了书上用的是:
this instanceof nop ? this : (obj || {})
这个就是我的疑问了,我的感觉就是这里nop换成bound也一样,希望大神能解解惑!!!
- 函数bind的实现
- Scala callccinterpreter 的bind函数实现
- js中bind函数的实现
- c++的bind()函数
- 函数的bind方法
- Bind 函数的使用
- 用虚函数或者bind、function实现线程的方法
- 模拟实现ES5中原生的bind函数
- 简单的bind实现
- winsock2 bind函数的功能
- winsock2 bind函数的功能
- 令人费解的bind函数
- javascript的bind()函数使用
- javascript中bind()函数实现和应用以及多次bind的结果和参数位置的思考
- C++11 bind函数实现原理图
- 利用闭包实现bind函数
- weak bind的std实现
- javascript---bind的实现方法
- uva 10491 Cows and Cars
- 输出json格式数据
- js 两数 的 加减乘数 运算
- try里面有个return 那后面的finally还执行吗?
- 关于js中单引号(')和双引号(")的使用以及转义的理解
- 函数bind的实现
- 日期2
- ios绘图基础
- 自动化测试第二阶段
- LeetCode刷题 (Python) | 155. Min Stack
- mysql ERROR 1045 (28000): Access denied for user解决方法
- javascript正则表达式中的一个奇葩问题 有关于参数g
- ios绘图demo,做一个涂鸦板(上)
- USACO-Section 2.4 Fractions to Decimals(模拟)