什么是apply,bind,call
这三者的作用都是用来改变this指向的,我们实现源码也是为了了解他的底层原理,方便使用。
手撕apply
Function.prototype.apply(obj,arr){
if(!obj){
obj= typeof window==='undefined'?global:window;//判断环境是在浏览器还是在node环境下
}
obj.fn=this;
let result=null;
if(arr===undefined || arr===null){
result=obj.fn(arr)
}else{
result=obj.fn(...arr)
}
delete obj.fn;
return result
}
这里我们需要知道一点,在obj.fn=this这一步中为什么要创建一个obj的fn属性?
首先我们的目的是将this指向obj,所以我们将另外一个函数放在obj.fn中,
这样的话,fn中的this自然就指向obj了。最后将其指针转向result中,然后删除这个属性就可以达到目的了。
手撕call
Function.prototype.apply(obj,...arr){
if(!obj){
obj=typeof window === 'undefined' ?global:window;
}
obj.fn=this;
let result=null;
result=obj.fn(...arr)
delete obj.fn;
return result;
}
手撕bind
Function.prototype.bind = function (obj, ...arg) {
if (!obj) {
obj = typeof window === 'undefined' ? global : window
}
let self = this
let args = arg
function f() {}
f.prototype = this.prototype
let bound = function () {
let res = [...args, ...arguments]
let obj = this instanceof f ? this : obj
return self.apply(obj, res)
}
bound.prototype = new f()
return bound
}
关于node环境和浏览器环境
1,浏览器环境中的this指向window,node环境中的this指向global
2,在浏览器中不同的浏览器厂商提供了不同的浏览器内核,浏览器依赖这些内核解析js,但是不同内核之间有些许的差异,所以需要考虑浏览器的兼容性。
node是对v8引擎进行了一定的封装,他对一些特殊用例进行了优化,提供了替代的API,使得v8在非浏览器环境下运行的更好。
总结
v8引擎,有两个环境支持js的解析, 一个是node,一个是浏览器。