prototype原型对象上绑定新增函数的方法
在开发中,为了需要我们通常会在已有的数据类型上面创建更多的方法,比如说,为数组对象Array添加一个返回最大值的方法,这个时候就需要使用到原型对象prototype,每一个构造函数都有一个原型对象,在该对象上面挂载的函数是所有通过该构造函数实例化的对象所共有的,这里就以在Array上面添加求取最大值方法为例子:
我们可以直接将该函数挂载到Array的原型对象上:
Array.prototype.max=function()
{
//.....
}
然后,需要明确一点就是,每次调用该函数,则该函数中的this会指向调用者,也就是对应的实例化对象,这一点我们可以下面代码验证:
let that;
const arr=[1,2,3]
Array.prototype.max=function()
{
that=this;
}
arr.max();
console.log(that === arr); //true
那我们就可以通过展开运算符…,将对应的数组展开,再调用Math中的max方法得到最大值:
const arr=[1,2,3]
Array.prototype.max=function()
{
return Math.max(...this)
}
console.log(arr.max()); //3
这样子就实现该功能啦!
但是,很多人会将max函数写成匿名函数,这样子不行! 因为对于匿名函数是没有自己的this的,也就是说,匿名函数的this是指向外面一级也就是上一级,如果你使用匿名函数,那么this就和你编写函数的位置有关系,我举个例子来验证:如果此时你将上面的函数改为匿名函数:
const arr=[1,2,3]
Array.prototype.max=()=>
{
return Math.max(...this)
}
console.log(arr.max()); //报错,...没有对应的运算对象
为什么?因为这里使用的是匿名函数,没有自己的this,因此在这个位置看上去,this就是指向的该位置的外面,也就是Arrar的原型对象的外部,那就是window,所以…window是错误的。
如果你还不理解,那么继续往下看!
我写一个代码来验证匿名函数的this指向和书写的位置有关系,我在一个对象中声明一个普通函数,则该普通函数的this会指向父作用域,也就是那个对象obj1,然后,我在普通函数内部写匿名函数,显然,该匿名函数的this就是父作用域,也就是普通函数的this指向,就是obj1,然后,我在匿名函数内部调用原型对象挂载max函数,然后打印出this。
在外面,我调用一次obj1的方法,以便于内部函数执行一遍。
接着,我再次编写一个函数obj,和上面的对象一样,我又书写一个普通函数在对象里面,让他的this指向obj,然后再普通函数内部书写匿名函数,让普通函数调用匿名函数,则匿名函数this就是指向obj,然后在匿名函数内部调用在obj1中已经执行过的array对象的max方法,查看max内部打印出来的this是指向函数所在的obj1还是函数调用的obj:
const obj1={
name:'zsy',
f:function(){
const fun=()=>{
Array.prototype.max=()=>
{
console.log("原型");
console.log(this);
// return Math.max(...this)
}
}
fun()
}
}
obj1.f();
const obj={
name:'xjd',
f:function(){
console.log("外部");
console.log(this);
const fun=()=>{
console.log("内部");
console.log(this);
arr=[1,2,3]
arr.max();
}
fun()
}
}
obj.f()
打印结果如下:
结果意思就是,在obj的普通函数内部和普通函数中匿名函数的this,均指向的是obj,但是!在arr数组调用max处,通过max函数打印出来的this却是指向obj1。
综上,如果你使用匿名函数书写这些新增函数,将会引发各种各样的this指针问题,也就没办法使用到调用该方法的实例化对象,因此,为了防止这种情况出现,尽量别使用匿名函数吧~!