如何建设一个网站,网站手机版模板免费下载,西安外包公司有哪些,公司注册公司代理一、call
#xff08;1#xff09;官方用法
call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
语法#xff1a;function.call(要绑定的this值#xff0c;参数#xff0c;参数#xff0c;…)。不一定这些参数都需要#xff0c;这些参数都…一、call
1官方用法
call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
语法function.call(要绑定的this值参数参数…)。不一定这些参数都需要这些参数都是可选的返回值使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值则返回 undefined。
// 不指定参数
var nickname global
function getName() {console.log(this.nickname);
}
getName() //global
getName.call() //global 在严格模式下this 的值将会是 undefined。当不给call指定参数时相当于将不改变this的指向在哪调用的就指向哪儿即没有传递第一个参数this的值将会被绑定为全局对象。
// 指定第一个参数
var name cat
var obj {name: dog
}
function getName() {console.log(this.name);
}
getName() //cat
getName.call(obj) //dog
console.log(obj)//{ name: dog} 当指定第一个参数时第一个参数代表新的this值当调用方法时该方法的this值会绑定到obj对象于是会访问这个对象的name属性。
//指定第一个参数和其他参数
var obj {user: Ducky,fn: function(a, b) {console.log(a b);console.log(this.user);}
}
var b obj.fn;
b.call(obj, 1, 2);
// 3
// Ducky 除了第一个参数其余参数都是用来做一些必要的运算等。运行到这应该不难发现使用Function.call()的时候函数是谁执行的是使用call绑定对象的之后call也把函数执行了。
相信你已经会用了试着写写实现原理。
2实现原理
实现call的关键在于
第一如何给函数绑定新的this
第二如何在绑定完this后把函数也给执行完毕
掌握了这两个关键那么一切都有迹可循了。接下来看看换成自己手写的是不是一样的效果
Function.prototype.my_call function(context) {// 如何实现绑定新的thiscontext.fn this //context[fn]this// 如何在调用call时把调用call的函数也执行context.fn()
} 是不是大吃一惊就实现了是的就是实现了核心原理就是这两个关键不信可以测试一下
var name cat
var obj {name: dog
}
function getName() {console.log(this.name);
}
getName() //cat
getName.my_call(obj) //dog
console.log(obj)//{ name: dog, fn: [Function: getName] } 真的绑定成功了接下来继续做点优化优化也有几个关键点
第一非得是函数才可以调用call
第二call除了接收第一个参数新的this外还可以接收一个参数列表
第三官方call调用后不会改变新的thisobj的结构在上述代码中obj内部新增了一个属性fn
第四当call不传第一个参数时需指向全局对象window
第五调用call时需得有返回值
第六当将this挂载到新的this上时后者已经存在该属性的情况下还是会改变后者的结构。
终极实现原理
Function.prototype.my_call function(context, ...args) {if (typeof this ! function) throw new TypeError(error)context context || windowlet fn Symbol(fn)context[fn] this //context.fn this const res context[fn](...args)delete context[fn]return res
} 虽然考虑了六种情况但是代码还是很可人这回它就是与官方的源码一样的效果和功能了简直不要太完美~
二、apply
1官方用法
apply() 方法调用一个具有给定 this 值的函数以及以一个数组或一个类数组对象的形式提供的参数。
语法function.apply(要绑定的this的值[参数参数参数…])返回值调用有指定 this 值和参数的函数的结果。
可见它跟call就只有一个区别提供参数的方式不同。apply 使用参数数组而不是一组参数列表。apply 可以使用数组字面量array literal如 fun.apply(this, [dog, cat])或数组对象如 fun.apply(this, new Array(dog, cat))还可以使用 arguments 对象作为 argsArray 参数。arguments 是一个函数的局部变量。它可以被用作被调用对象的所有未指定的参数。这样在使用 apply 函数的时候就不需要知道被调用对象的所有参数及其个数。可以直接使用 arguments 来把所有的参数传递给被调用对象。被调用对象接下来就负责处理这些参数要解构要切割要指定索引都可以。
既然apply的用法和call几乎相同只是除第一个参数外其余参数传递方式不一样那么我们直接在my_call的手写上修改传递参数的形式即可。
2实现原理
Function.prototype.my_apply function(context, args) {if (typeof this ! function) throw new TypeError(error)context context || windowlet fn Symbol(fn)context[fn] this //context.fn this const res context[fn](...args)delete context[fn]return res
} 这。。。。还是测试一下吧
var obj {user: Ducky,fn: function(a, b) {console.log(a b);console.log(this.user);}
}
var b obj.fn;
b.my_apply(obj, [1, 2]);
// 3
// Ducky 好了成功了该考虑的已经在手写call的时候考虑过了就是这么的干净利落。
三、bind
1官方用法
bind() 方法创建一个新的函数在 bind() 被调用时这个新函数的 this 被指定为 bind() 的第一个参数而其余参数将作为新函数的参数提供调用时使用。
语法function.bind(要绑定的this值参数1参数2参数3)。
这里说明第一个参数是如果为空或者为null||undefined执行作用域的this将被视为形函数的的this值其余参数当目标函数被调用时被预置入绑定函数的参数列表中的参数可有可无也可在返回的新函数里面传递。返回值是返回一个原函数的拷贝并拥有指定的 this 值和初始参数。
举个例子
var name cat
var obj {name: dog,fn: foo
}
function foo(a, b) {console.log(this.name, a b);return a b
}
const bar foo.bind(obj)
bar(3, 4)
//dog 7 2实现原理
从上述例子可以看出bind()会创建一个新的绑定函数bar。
实现bind函数的关键在于
第一如何新建一个绑定函数
第二如何将拿到在call传递的参数和调用新建的绑定函数传递的参数并结合
第三如果使用new操作符操作新建的那个绑定函数this又该如何指向
先讨论以下前两个关键新建一个绑定函数直接在call内部返回一个函数即可将两个地方的传递的参数都传递给执行绑定函数。
Function.prototype.my_bind function(context, ...args1) {// 保存外部函数的thisconst _this thisreturn function bound(...args2) {//返回一个新函数//返回值return _this.call(context, ...args1, ...args2)}
} 不要惊讶在实现bind函数内部用的是call||apply大不了用刚刚手写的my_call||my_apply。大体上就实现了测试一下
var name cat
var obj {name: dog,fn: foo
}
function foo(a, b) {console.log(this.name, a b);return a b
}
const bar foo.my_bind(obj)
bar(3, 4)
//dog 7 再来考虑第三个问题
//官方bind
const bar foo.bind(obj)
new bar(3, 4)//cat 7
//手写的my_bing
const bar foo.my_bind(obj)
new bar(3, 4) //dog 7 从上可以看出当使用new操作符操作新的函数bar时官方的bind会忽略绑定的this值但是前置参数依然会提供给铭记函数而我们手写的my_bind原封不动这肯定得改
现在无非是当使用new运算符构造新建的绑定函数bar时foo.bind(obj)中foo的·this指向不指向obj也不指向全局对象而是会指向实例对象new bar()的执行作用域接下来可以理一下思路
//目标(new bar)._proto_foo.prototype
//即如果新建的绑定函数被newbind的调用函数就会变成实力对象的构造函数
//接下来的操作都是在my_bind函数内部操作
//借助一个辅助函数
const helpfunction(){}
bound.prototypenew help()//继承到了foobind的调用函数的原型
if(this.prototype){//this指的是bind的调用函数help.prototypethis.prototype}
通过一通操作得到new help()._proto_help.prototypethis.prototypebound.prototypethis是什么取决于调用bind函数的函数是什么在这里是foo所以new bound()._proto_bound.prototypefoo.prototype那么调用bind函数的this到底指向什么取决于新建的绑定函数bar有没有被new如果没有则看传递的第一个参数第一个参数为空则为全局对象不为空则为指定的对象如果被new了那么调用nind函数的this指向新建的绑定函数的执行作用域bind最终实现方式是
Function.prototype.my_bind function(context, ...args1) {if (typeof this ! function) {throw new TypeError(error)}context context || windowconst _this thisconst help function() {}if (this.prototype) {help.prototype this.prototype}const bound function(...args2) {return _this.call(this instanceof help ? this : context,...args1,...args2)}bound.prototype new help()return bound
} 最后
最近找到一个VUE的文档它将VUE的各个知识点进行了总结整理成了《Vue 开发必须知道的36个技巧》。内容比较详实对各个知识点的讲解也十分到位。 有需要的小伙伴可以点击下方卡片领取无偿分享