第26天 说说bind、call、apply的区别?并手写实现一个bind的方法
call
和apply
都是为了解决改变this
的指向。作用都是相同的,只是传参的方式不同。
除了第一个参数外,call
可以接收一个参数列表,apply
只接受一个参数数组。 bind
绑定完之后返回一个新的函数,不执行。
Function.prototype.myCall = function (context = window) {
context.fn = this;
var args = [...arguments].slice(1);
var result = context.fn(...args);
// 执行完后干掉
delete context.fn;
return result;
}
Function.prototype.myApply = function (context = window) {
context.fn = this;
var result
// 判断 arguments[1] 是不是 undefined
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result;
Function.prototype.myBind = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
var _this = this
var args = [...arguments].slice(1)
// 返回一个函数
return function F() {
// 因为返回了一个函数,我们可以 new F(),所以需要判断
if (this instanceof F) {
return new _this(...args, ...arguments)
}
return _this.apply(context, args.concat(...arguments))
}
}
上面同学说的太好了,简洁好记!!忍不住重复一遍。
call() 和 apply() 作用都是改变 this 的指向,区别是传参的方式不同。除了第一个参数外,call() 可以接收一个参数列表,apply() 只接受一个参数数组。 bind() 绑定完之后返回一个新的函数,不执行。
Function.prototype.myBind(context,...args){
return function(){
return this.apply(context,args)
}
}
1:call与apply基本一样,唯一不一样的是接收的参数
2:bind则是改变this后返回一个新函数
function bindFun(cb, ctx) {
// 一些限制没加
return (...args) => cb.call(ctx || this, args);
}
bindFun(b, a)();
Function.prototype.customBind = function (ctx, ...args) {
return (...args2) => this.apply(ctx, args.concat(args2));
};
bind
, call
, apply
三者都可以改变 this
的指向。
其中 call
和 apply
为立即执行,两者效果等价,只有在传參形式上有所区别。call
需要把参数一个一个传入 fun.call(obj, arg1, arg2, arg3,...)
而 apply
接受一个数组作为参数 fun.apply(obj, [arg1, arg2, arg3, ...])
。
bind
则是延时执行。const fb = fun.bind(obj) fb(arg1, arg2, ...)
在使用 bind
之后,只会返回一个修改了作用域的函数,等再次调用时才会执行。
function customBind(fun, obj) {
return (...args) => {
fun.apply(obj, [...args]);
};
}
Function.prototype.call1 = function(fn, ...args) {
const symbol = Symbol()
fn = fn || window
fn[symbol] = this
let result = fn[symbol](...args)
delete fn[symbol]
return result
}
Function.prototype.apply1 = function(fn, arr = []) {
// const symbol = Symbol()
// fn = fn || window
// fn[symbol] = this
// let result = fn[symbol](...arr)
// delete fn[symbol]
// return result
return this.call1(fn, ...arr)
}
md5-72d44af7d304a44d682201b6e5f98e70
Function.prototype.bind1 = function(fn, ...args) {
const _this = this
const bound = function(...arguments) {
return _this.apply1(this instanceof bound ? this : fn, [...args, ...arguments])
}
bound.prototype = Object.create(_this.prototype || null)
return bound
}
https://www.runoob.com/w3cnote/js-call-apply-bind.html
这个帖子对于三者区别写的很详细
bind() 方法不会调用函数,他会绑定其他元素,当其他元素触发事件时改变 this 的指向
语法:fun.bind(thisArg, arg1, arg2, ...)
参数:
注意:
实现 bind 方法
Function.prototype._bind = function() {
if (typeof this !== 'function') {
throw new Error(
'Function.prototype.bind - what is trying to be bound is not callable'
)
}
let self = this
// 需要传入self的参数
let args = Array.prototype.slice.call(arguments, 1)
return function() {
return self.apply(self, args)
}
}
Function.prototype._bind = Function.prototype._bind || function() {}
call() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向
语法:fun.call(thisArg, arg1, arg2, ...)
参数:
注意:
实现 call 方法
Function.prototype._call = function() {
if (typeof this !== 'function') {
throw new Error(
'Function.prototype.bind - what is trying to be bound is not callable'
)
}
let self = this
let pointTo = arguments[0] || window
// 需要传入self的参数
let args = Array.from(arguments).slice(1)
pointTo.fn = self
pointTo.fn(...args)
// 需要传入self的参数
}
Function.prototype._call = Function.prototype._call || function() {}
apply() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向,参数为数组形式
语法:fun.apply(thisArg, [arg1, arg2, ...])
参数:
注意:
Function.prototype._apply = function() {
if (typeof this !== 'function') {
throw new Error(
'Function.prototype.bind - what is trying to be bound is not callable'
)
}
let self = this
let pointTo = arguments[0] || window
// 需要传入self的参数
let [args] = Array.from(arguments).slice(1)
pointTo.fn = self
pointTo.fn(...args)
// 需要传入self的参数
}
Function.prototype._apply = Function.prototype._apply || function() {}
有错请指出,感谢
来和我一起刷3+1吧
gitHub: https://github.com/Renato-Z/exercises/blob/master/history.md
// call
Function.prototype._call = function (target=window, ...res) {
target._fun = this;
const ret = target._fun(...res);
delete target._fun;
return ret;
}
// apply
Function.prototype._apply = function (target=window, list=[]) {
target._fun = this;
const ret = target._fun(...list);
delete target._fun;
return ret;
}
// bind
Function.prototype._bind = function (target, ...res) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
const that = this;
const _func = function(...args) {
// 判断当前韩式是直接访问还是通过new进行构造
return that.apply(this instanceof _func ? this : target, res.concat(args));
}
// 添加一层原型,防止修改_func.prototype时影响到this.prototype
_func.prototype = Object.create(this.prototype);
return _func;
}
call、apply和bind作用都是为了改变this的指向
call、apply会立即执行此函数,两者等价,第一个参数一致。apply第二个参数是数据,call是接受一个参数列表
bind是返回一个新的函数。第二个参数也是一个参数列表
function bind(f,o) {
if (f.bind) return f.bind(o)
else return function() {
renturn f.apply(o,arguments);
}
}
call() 和 apply() 作用都是改变 this 的指向,区别是传参的方式不同。除了第一个参数外,call() 可以接收一个参数列表,apply() 只接受一个参数数组。 bind() 绑定完之后返回一个新的函数,不执行。
Function.prototype.customCall = function (context) {
context.fn = this;
let params = Array.from(arguments)
let result = context.fn(...params.slice(1))
delete context.fn;
return result;
}
Function.prototype.customApplay = function (context) {
context.fn = this;
let result = context.fn(...arguments[1])
delete context.fn;
return result;
}
Function.prototype.customBind = function (context) {
context.fn = this;
let params = Array.from(arguments)
return function F() {
let result = context.fn(...(params.slice(1).concat(Array.from(arguments))))
return result;
}
}
const run = function(x,y){ return x + y + this.z }
const obj = {z: 3}
const res = run.bind(obj, 1, 2)
console.log(res())
Function.prototype.myBind = function(){
if (typeof this !== 'function') {
throw new TypeError('not funciton')
}
const [context, ...args] = arguments
const symbolFn = Symbol('fn')
context.symbolFn = this
return function() {
const res = context.symbolFn(...args)
delete context.symbolFn
return res
}
}
console.log(run.myBind(obj, 4, 5)())
Function.prototype.mybind = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
let _this = this
let arg = [...arguments].slice(1)
return function F() {
// 处理函数使用new的情况
if (this instanceof F) {
console.log(this)
return new _this(...arg, ...arguments)
} else {
console.log(arguments)
return _this.apply(context, arg.concat(...arguments))
}
}
}
Most helpful comment
call
和apply
都是为了解决改变this
的指向。作用都是相同的,只是传参的方式不同。除了第一个参数外,
call
可以接收一个参数列表,apply
只接受一个参数数组。bind
绑定完之后返回一个新的函数,不执行。