
实现bind方法
js
Function.prototype.myBind = function (context, ...args) {
// 新建一个变量赋值this,表示当前函数
const fn = this
// 判断有没有参数传进来
args = args ? args : []
// 返回一个函数,并调用fn
return function newFn(...newFnArgs) {
if (this instanceof newFn) {
return new fn(...args, ...newFnArgs)
}
return fn.apply(context, [...args, ...newFnArgs])
}
}js
// bind返回一个函数,对于函数来说有两种方式调用,一种是直接调用,一种是通过new的方式调用
// 对于直接调用来说,这里选择了apply的方式实现,但是对于参数需要注意以下情况:因为bind可以试下类似的代码:f.bind(obj,1)(2),所以我们需要将两边的参数拼接起来
// new调用的话,不会被任何方式改变this,所以对于这种情况我们需要忽略传入的this
// 简洁版本
Function.prototype.myBind = function (context, ...outerArgs) {
// this --> func context --> obj outerArgs --> [10,20]
let self = this
// 返回一个函数,...innerArgs为实际调用时传入的参数
return function F(...innerArgs) {
// 考虑new的方式
if (self instanceof F) {
return new self(...outerArgs, ...innerArgs)
}
// 把func执行,并且改变this即可,返回改变了this的函数,参数合并
return self.apply(context, [...outerArgs, ...innerArgs])
}
}js
Function.prototype.myBind = function (context, ...args) {
if (!context || context === null) {
context = window
}
let fn = Symbol()
context[fn] = this
let _this = this
const result = function (...innerArgs) {
if (this instanceof _this === true) {
this[fn] = _this
this[fn](...[...args, ...innerArgs])
} else {
context[fn](...[...args, ...innerArgs])
}
}
result.prototype = Object.create(this.prototype)
return result
}
//用法如下
function Person(name, age) {
console.log(name) //'我是参数传进来的name'
console.log(age) //'我是参数传进来的age'
console.log(this) //构造函数this指向实例对象
}
// 构造函数原型的方法
Person.prototype.say = function () {
console.log(123)
}
let obj = {
objName: '我是obj传进来的name',
objAge: '我是obj传进来的age',
}
// 普通函数
function normalFun(name, age) {
console.log(name) //'我是参数传进来的name'
console.log(age) //'我是参数传进来的age'
console.log(this) //普通函数this指向绑定bind的第一个参数 也就是例子中的obj
console.log(this.objName) //'我是obj传进来的name'
console.log(this.objAge) //'我是obj传进来的age'
}
//先测试作为构造函数调用
let bindFun1 = Person.myBind(obj, '我是参数传进来的name')
let a = new bindFun('我是参数传进来的age')
a.say() //123
//再测试作为普通函数调用
let bindFun2 = normalFun.myBind(obj, '我是参数传进来的name')
bindFun('我是参数传进来的age')js
Function.prototype.myBind = function (context) {
if (typeof this !== 'function') {
throw new Error('Function.prototype.bind - what is trying to be bound is not callable')
}
var self = this
var args = Array.prototype.slice.call(arguments, 1)
var fNOP = function () {}
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments)
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs))
}
fNOP.prototype = this.prototype
fBound.prototype = new fNOP()
return fBound
}
Function.prototype.bindFn = function bind(thisArg) {
if (typeof this !== 'function') {
throw new TypeError(this + 'must be function')
}
var self = this
var args = [].slice.call(arguments, 1)
var bound = function () {
var boundArgs = [].slice.call(arguments)
console.log(this, '#####################', self)
return self.apply(thisArg, args.concat(boundArgs))
}
return bound
}
// 测试
var obj = {
name: '若川',
}
function original(a, b) {
console.log(this.name)
console.log([a, b])
}
var bound = original.bindFn(obj, 1)
bound(2) // '若川', [1, 2]
Function.prototype.bindFn2 = function bind(thisArg) {
if (typeof this !== 'function') {
throw new TypeError(this + 'must be a function')
}
var self = this
var args = [].slice.call(arguments, 1)
var bound = function () {
var boundArgs = [].slice.call(arguments)
var finalArgs = args.concat(boundArgs)
if (this instanceof bound) {
if (self.prototype) {
function Empty() {}
Empty.prototype = self.prototype
bound.prototype = new Empty()
}
var result = self.apply(this, finalArgs)
var isObjet = typeof result === 'object' && result !== null
var isFunction = typeof result === 'function'
if (isObjet || isFunction) {
return result
}
return this
} else {
return self.apply(thisArg, finalArgs)
}
}
return bound
}
Function.prototype.bind =
Function.prototype.bind ||
function bind(thisArg) {
if (typeof this !== 'function') {
throw new TypeError(this + 'must be a function')
}
var self = this
var args = [].slice.call(arguments, 1)
var bound = function () {
var boundArgs = [].slice.call(arguments)
var finalArgs = args.concat(boundArgs)
if (this instanceof bound) {
if (self.prototype) {
function Empty() {}
Empty.prototype = self.prototype
bound.prototype = new Empty()
}
var result = self.apply(this, finalArgs)
var isObject = typeof result === 'object' && result !== null
var isFunction = typeof result === 'function'
if (isObject || isFunction) {
return result
}
return this
} else {
return self.apply(thisArg, finalArgs)
}
}
}
