js深入突破,this指针问题,实现call的原理,通过原生改变代码逻辑!
大致介绍
everyone,这里是小m马的第二次技术分享,关于该如何正确的使用this的指向,来通过自己的逻辑能力来手写一个call的原理,当然这个过程中相信大家也会对call的理解会更深刻,虽然我们平时不用运用到call,但是这个核心的问题是在代开的开发中会经常遇到的,逻辑,this,call,对象,好了,根据这四个关键字,我们进行阅读!
举个例子!进行对比,首先我们看call的作用
var foo = {
value:1
}
var bar = function(name,age){
console.log(name)
console.log(age)
console.log(this.value)
}
bar.call(foo,'kewen',18)
//1,kewen,18 打印结果
这段call的原生代码执行出来后会打印出,1,kewen,18 ,接下来进行我们的手写call,仔细观察每一步
var foo = {
value:1
}
Function.prototype.call2=(context)=>{
context.fn = this
var ages = []
for(let i = 1 ; i<arguments.length;i++){
//age.push('aguments['+i+']')
args.push(arguments[i]);
}
eval('context.fn('+ages+'')')
delete context.fn
}
var bar = function(){
console.log(name)
console.log(age)
console.log(this.value)
}
bar.call2(foo,'kewen',18)
// 1,kewen,18
第一步声明一个对象,内有属性value:1,然后可以发现接下来是两个函数,
直接看bar这个函数,打印三个属性,然后是执行了函数bar的方法call2(也就是我们自己通过原型建造的一个函数方法)传递了三个参数
1.foo对象
2.kewen(字符串)
3.18(数字)
接着我们看中间的部分,小m马在bar这个函数的原型中添加了一个叫做call2的方法,这也就是为什么我们可以使用bar.call2(foo,‘kewen’,18)的原因
我们在bar的原型中添加了call2的方法,并且传入了context的参数,也就是foo,
接下来是步骤解释:
- 给context添加了一个属性fn,值为this,this为call2,而call2其实是bar的原型,所以是指向bar函数的,但是千万记住this的话是谁调用指向谁的。
- 遍历了arguments添加入空数组,arguments也就是函数的参数,那么有些朋友会疑惑这个call2的参数我们只传递了context为什么我们还要进行遍历,其实不然,我们可以看到在外面我们执行方法时是bar.call2(foo,‘kewen’,18),三个参数,虽然在原型中我们只拿到了context,但是arguments依然会包括其他两个
- 执行context.fn,在上面我们交代了,这个this指向了bar的原型函数,那bar没有value为什么可以打印出1来,因为我们把foo.fn 的this指向了bar的属性值call2,所以这call2的this函数领域内是包含了foo的,也就是说foo和call2共享了同一个this,那么就可以解释为什么能打印出1来了,而call2本身的this是可以找到bar的,那么也打印出kewen和18也合情合理了
- 至于第三步为什么要删除这个方法,是因为避免不必要垃圾残存和以后带来的影响
注释:至于为什么可以给函数添加一个方法,这是关于原型的知识点,以后小m马会进行解析,希望大家持续关注,如果大家有观点的地方,那是大家对自己理解的方式表达的不同,希望理解!
解释eval函数的作用
Function.prototype.call2 = function (context) {
context.fn = this;
var args = [];
for (var i = 1, len = arguments.length; i < len; i++) {
args.push(arguments[i]);
//age.push('aguments['+i+']')
}
// eval('context.fn(' + args + ')');
context.fn(...args)
delete context.fn;
}
// 测试一下
var foo = {
value: 1
};
function bar(name, age) {
console.log(name)
console.log(age)
console.log(this.value);
}
bar.call2(foo, 'kevin', 18);
eval函数,这是一个非常强大的方法,但是一般情况下大家也用不怎么到,大多数情况下用于计算作用,当然执行函数也没有问题,所以我们在 这里使用,就是执行一下bar这个函数,当然这个写法有点让人奇奇怪怪的,所以小m马把他翻译一下
今天分享到此结束,希望大家可以持续关注小m马,小m马每天都在进步,分享硬货js知识,本篇文章在面试的时候和对自己的提升都有很大的作用,再一次感谢大家的观看!!!
这里是小m马,每周的前端硬货分享,大家一起探讨可以私信我!!!
(上一篇博客中说到会对if的优化有升级说明和讲解,我们后面会写出来,是在感到抱歉的是这一次没有进行更新,会补上哦!)