We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
apply 和 call 作用一样都是为了动态的改变 this
var obj = { a: '1' } var a = '2' function func (arr,brr) { ... } func() // '2' func.apply(obj,[arr,brr]) // '1' func.call(obj, arr, brr) // '2'
apply 接收一个参数数组,call 接收参数,参数有多少就传入多少。
bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。‘ bind 的特点
bind()
this
返回一个新建的新函数 返回的函数以 bind 方法中第一个参数作为 this 其他参数都会传入进去
先来看一道题。
var altwrite = document.write; altwrite("hello"); // Uncaught TypeError: Illegal invocation
this 丢失导致的问题
altwrite.call(document, 'hello') altwrite.bind(document)("hello")
call 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
返回值取决于这个方法
Function.prototype.myCall = function(context){ if( !context ){ context = window } else{ context = Object(context) } const specialPrototype = Symbol('特殊的属性'); context[specialPrototype] = this; let arg = [...arguments].slice(1) let value = context[specialPrototype](...arg) delete context.fn return value }
注意事项:
context = Object(context)
Function.prototype.myApply = function (context) { if( !context ){ context = window } else{ context = Object(context) } const specialPrototype = Symbol('特殊的属性'); context[specialPrototype] = this; function isArrayLike(o) { if (o && // o不是null、undefined等 typeof o === 'object' && // o是对象 o.length >= 0 && // o.length为非负值 o.length === Math.floor(o.length) && // o.length是整数 o.length < 4294967296) // o.length < 2^32 return true else return false } let args = arguments[1]; let result if(args) { if(!Array.isArray(args) && !isArrayLike(args)){ throw new TypeError('第二个参数不是对象'); }else { args = Array.from(args); // args = args.Array.prototype.slice() result = context[specialPrototype](...args) // 展开数组,传递函数参数 } }else{ result = context[specialPrototype]() } delete context[specialPrototype]; return result; }
apply
bind 的特点
函数调用,改变this
返回一个绑定this的函数
接收多个参数
支持柯里化形式传参 fn(1)(2)
一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。
Function.prototype.mybind = function (context) { let self = this; let arg = [...arguments].slice(1) return function() { let newArg = [...arguments]; return self.apply(context, arg.concat(newArg)) } }
我感到了我和这个语言有一层膜 这个膜经常会在一些特殊的场合下我能感受到它 如果我能突破它 我将功力大增。就好比上面的代码 看似没啥问题但
var foo = { value: 1 }; Function.prototype.mybind = function (context) { let self = this; //var args = Array.prototype.slice.call(arguments, 1); let arg = [...arguments].slice(1) return function() { let newArg = [...arguments]; return self.apply(context, arg.concat(newArg)) } } function bar(name,jj) { console.log(this.value) console.log(name); } var n = bar.mybind(foo,1); var w = new n; console.log(w) // {}
拷贝源函数:
Object.create
返回拷贝的函数
调用拷贝的函数:
instanceof
new
context
bind
Function.prototype.mybind = function (objTHis, ...params) { const thisFn = this // 获取调用的函数 bar.mabind this === bar let fToBind = function (...secondParams) { const isNew = this instanceof fToBind // 查看是否是 new 调用了 const context = isNew ? this : Object(objThis); //Object(objThis) 这里包装了一下 return thisFn.call(coontext, ...params, ...secondParams); } if(thisFn.prototype) { // 将调用这个bind的函数的prototype 赋值给新创建的fToBind函数。 fToBind.prototype = Object.create(thisFn.prototype); } }
Function.prototype.bind2 = function (context) { 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(); // 这里注意 这里是将 fBound 的原型指向了 别的地方 就算 被 new 之后 原型的再次改动也不会去影响到 this (绑定函数的原型链) // fToBind.prototype = Object.create(thisFn.prototype); //和这一步有一样的效果 return fBound; }
你能手写实现一个bind吗?
call 和 apply 的模拟实现
The text was updated successfully, but these errors were encountered:
No branches or pull requests
apply 和 call 简单的用法和两者之间的区别
apply 和 call 作用一样都是为了动态的改变 this
apply 接收一个参数数组,call 接收参数,参数有多少就传入多少。
bind
bind()
方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入bind()
方法的第一个参数作为this
,传入bind()
方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。‘bind 的特点
先来看一道题。
this 丢失导致的问题
call 的特点
call 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
返回值取决于这个方法
实现 call
注意事项:
context = Object(context)
将它绑定到原始值的实例对象上。实现 apply
注意事项:
apply
接受第二个参数为类数组对象,要去判别是否是类数组 然后将其转化成数组实现bind
bind 的特点
函数调用,改变this
返回一个绑定this的函数
接收多个参数
支持柯里化形式传参 fn(1)(2)
一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。
我感到了我和这个语言有一层膜 这个膜经常会在一些特殊的场合下我能感受到它 如果我能突破它 我将功力大增。就好比上面的代码 看似没啥问题但
最终修改版
拷贝源函数:
Object.create
复制源函数的prototype给fToBind返回拷贝的函数
调用拷贝的函数:
instanceof
判断函数是否通过new
调用,来决定绑定的context
[你能手写实现一个
bind
吗?][https://juejin.cn/post/6844903906279964686]
参考
你能手写实现一个
bind
吗?call 和 apply 的模拟实现
The text was updated successfully, but these errors were encountered: