bind介绍
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用
参看官网Function.prototype.bind()
bind特性总结:
- 函数A调用bind方法时,返回新的函数B
- 函数B在执行时,具体功能实际上还是A,只不过this指向bind()中第一个参数,不传的话是window
- 函数A调用bind方法时,可以传递参数o, x, y, z...
- 函数B在执行的时候,传递的参数会拼接到 x, y, z的后面 一并在内部传给A
- new B()构造函数依旧是A,而且o不会起任何作用
手写代码1.0
实现1、2两点
<script>
Function.prototype.newBind = function (targetObj) {
var self = this;// this在这里指向的是目标函数
var f = function () {
// 真正执行的是self,也就是外面的this
// 这里面的this是window
return self.apply(targetObj || window)
}
return f
}
function show () {
console.log("show函数被执行了")
console.log(this)
}
var obj = { x: 20 }
var newShow = show.newBind(obj)
newShow()
// 输出
show函数被执行了
{ x: 20 }
</script>
手写代码2.0
在1.0基础上,加了特性3
// 2.0
Function.prototype.newBind = function (targetObj) {
var self = this;// this在这里指向的是目标函数
// console.log(arguments)
// console.log(arguments[0] === targetObj) // true arguments[0]就是targetObj
// 实际newBind时传入的参数是下标1以后的
var args = [].slice.call(arguments, 1)
var f = function () {
// 真正执行的是self->this
// 这里面的this是window
return self.apply(targetObj || window, args)
}
return f
}
function show () {
console.log("show函数被执行了")
console.log(this, arguments)
}
var obj = { x: 2 }
// 这里的
var newShow = show.newBind(obj, 3, 4)
newShow()
// 输出
show函数被执行了
{ x: 2 } [Arguments] { '0': 3, '1': 4 }
手写代码3.0
在2.0基础上,加了特性4
// 3.0
Function.prototype.newBind = function (targetObj) {
var self = this;// this在这里指向的是目标函数
// console.log(arguments)
// console.log(arguments[0] === targetObj) // true arguments[0]就是targetObj
// 实际newBind时传入的参数是下标1以后的
var args = [].slice.call(arguments, 1)
var f = function () {
// 获取这个要返回函数的参数
var _args = [].slice.call(arguments, 0)
// 真正执行的是self->this
// 这里面的this是window
return self.apply(targetObj || window, args.concat(_args))
}
return f
}
function show () {
console.log("show函数被执行了")
console.log(this, arguments)
}
var obj = { x: 2 }
var newShow = show.newBind(obj, 3, 4)
newShow(5)
console.log(new newShow().constructor === show) // false
// 输出
show函数被执行了
{ x: 2 } [Arguments] { '0': 3, '1': 4, '2': 5 }
false
手写代码4.0
在3.0基础上,加了特性5,new B()的构造函数依旧是A
// 4.0
Function.prototype.newBind = function (targetObj) {
var self = this;// this在这里指向的是目标函数
// 实际newBind时传入的参数是下标1以后的
var args = [].slice.call(arguments, 1)
var temp = function () {}
var f = function () {
// 获取这个要返回函数的参数
var _args = [].slice.call(arguments, 0)
return self.apply(targetObj || window, args.concat(_args))
}
temp.prototype = self.prototype
f.prototype = new temp()
return f
}
function show (x) {
console.log("show函数被执行了")
this.x = x
console.log(this, arguments)
}
var obj = { x: 2 }
var newShow = show.newBind(obj, 3)
var newShowObj = new newShow()
console.log(newShowObj.constructor === show) // true
console.log(newShowObj.x) // undefined
// 输出
show函数被执行了
{ x: 3 } [Arguments] { '0': 3 }
true
undefined
这里有一个问题,就是newShowObj.x是undefined。
这是因为show函数中的this.x在实际执行的时候,this指向targetObj || window,
所以得对创建实例对象这种情况特殊处理。
手写代码5.0
只改动4.0中的第14行代码
// 5.0
Function.prototype.newBind = function (targetObj) {
var self = this;// this在这里指向的是目标函数
// console.log(arguments)
// console.log(arguments[0] === targetObj) // true arguments[0]就是targetObj
// 实际newBind时传入的参数是下标1以后的
var args = [].slice.call(arguments, 1)
var temp = function () {}
var f = function () {
// 获取这个要返回函数的参数
var _args = [].slice.call(arguments, 0)
// 真正执行的是self->this
// 这里面的this是window
return self.apply(this instanceof temp ? this : (targetObj || window), args.concat(_args))
}
temp.prototype = self.prototype
f.prototype = new temp()
return f
}
function show (x) {
console.log("show函数被执行了")
this.x = x
console.log(this, arguments)
}
var obj = { x: 2 }
var newShow = show.newBind(obj, 3)
var newShowObj = new newShow()
console.log(newShowObj.constructor === show) // true
console.log(newShowObj.x)
// 输出
show函数被执行了
show { x: 3 } [Arguments] { '0': 3 }
true
3
补充
①__proto__和constructor属性是对象所独有的;
② prototype属性是函数所独有的。
constructor属性也是对象才拥有的,它是从一个对象指向一个函数,含义就是指向该对象的构造函数,每个对象都有构造函数(本身拥有或继承而来)
参考文章:blog.csdn.net/cc188688768…
本人前端小菜鸟一只,如有错误或疏漏,欢迎评论交流!