1 原型重定向概念
概念:改变内置原型指向
使用场景:批量给内置原型上增加属性和方法
存在的问题:
- 重新定向的对象中没有constructor
- 原始的原型对象上,存放的属性方法,不会放到重新定向的对象上,导致实例不能再用原始的那些方法了
- 原始的原型对象不被占用后,会被内存释放掉
- 内置类的原型都不允许重定向
2 重定向陪写及问题解决
2.1 基础写法
function Func() {}
// 向原型上扩展 A B C D 四方法
Func.prototype.A = function () {};
Func.prototype.B = function () {};
Func.prototype.C = function () {};
Func.prototype.D = function () {};
let f1 = new Func;
console.log(f1);
输出结果如下,可见 f1 原型上有 A B C D 四方法,且 Func 上没有 constructor。
未重定向的函数原型上有 constructor ,如下
重定向一般用于批量添加属性和方法的场景中,若如上所写,则需要写很多 Func.prototype ,非常麻烦且不高级,优化见2.2
2.2 优化1版写法
为解决写法麻烦的问题,咱可以直接让 Func2.prototype 指向一个对象。
为解决没有 constructor 的问题,咱可以手动添加 constructor。
// 直接更改 Func.prototype 的指向
Func.prototype = {
// 可以手动设置constructor
constructor: Func,
E: function () {},
F: function () {}
};
let f2 = new Func;
console.log(f2);
输出结果如下,可见 constructor 和 E F 两方法已添加至原型,但是 2.1 中添加的 A B C D 已经被覆盖了,这样在多人合作开发中存在隐患。
2.3 优化2版写法
两个原型对象合并,用新的原型对象替换原始的原型对象【 注意:如果新老有个属性方法相同,则新的值会替换老的值 】
Func.prototype = Object.assign(Func.prototype, {
G: function () {},
H: function () {}
});
Object.assign() 知识补充:
用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。
- 它将返回目标对象
- 目标对象本身会改变
- 若源对象与目标对象具有相同的属性,你们源对象的属性值会覆盖目标对象的属性值
Object.assign( target, ...sources ) // target:目标对象,sources:源对象
输出结果如下,保留了原来的所有属性和方法,【 注意:如果新老有个属性方法相同,则新的值会替换老的值 】
2.4 升级版写法
为解决新老两个属性方法同名覆盖问题。
把老的原型对象作为新原型对象的上级原型(即增长原型链)。
// 先创建一个原型指向 Func.prototype 的新对象 protoNew
let protoNew = Object.create(Func.prototype);
// 然后让新对象与 【需要批量扩展到 Func 上的扩展的方法】 合并
protoNew = Object.assign(protoNew, {
H: function () {},
I: function () {}
});
// 最后更改 Func.prototype 的指向
Func.prototype = protoNew;
输出结果如下:新添加的方法都存在,且之前添加的方法存在于原型链上,可以通过原型链查找到并使用。
3 笔试题分析
分析输出结果
function fun() {
this.a = 0
this.b = function () {
alert(this.a)
}
}
fun.prototype = {
b: function () {
this.a = 20
alert(this.a)
},
c: function () {
this.a = 30
alert(this.a)
},
}
var my_fun = new fun()
my_fun.b()
my_fun.c()
画图讲解如下