js中原型重写的几种方案

3,463 阅读2分钟

前言

有时候我们总会遇到,像内置的原型上添加方法,添加一个两个是很简单的,但当我们需要批量的往原型上添加方法时,我们就需要重写原型,那我们接下来看看有哪几种方案?

function Func() {

}
Func.prototype.XX = function () {};

Func.prototype.A = function () {};
Func.prototype.B = function () {};
Func.prototype.C = function () {};
Func.prototype.D = function () {};

js原型重写的方案

1、Func.prototype={}

function Func() {

}
Func.prototype = {
	// 1.可以手动设置constructor
	constructor: Func,
	A: function () {},
	B: function () {}
};

这种方案,缺失了constructor,也缺失了原始原型对象的上的属性和方法

2、Object.assign()

function Func() {

}
Func.prototype = Object.assign(Func.prototype, {
	A: function () {},
	B: function () {}
})

两个原型对象合并,用新的原型对象替换原始的原型对象(问题:如果新老有个属性方法相同,则新的值会替换老的值)

3、Object.create()和Object.assign()

let protoNew = Object.create(Func.prototype);
protoNew = Object.assign(protoNew, {
	A: function () {},
	B: function () {}
});
Func.prototype = protoNew;

let f = new Func;
console.log(f);

接下来,我们看一下原型链重写的题

面试题

function Fn() {
	let a = 1;
	this.a = a;
}
Fn.prototype.say = function () {
	this.a = 2;
}
Fn.prototype = new Fn;
let f1 = new Fn;
Fn.prototype.b = function () {
	this.a = 3;
};
console.log(f1.a);
console.log(f1.prototype);
console.log(f1.b);
console.log(f1.hasOwnProperty('b'));
console.log('b' in f1);
console.log(f1.constructor == Fn);

function Foo() {
    getName = function () {
        console.log(1);
    };
    return this;
}
Foo.getName = function () {
    console.log(2);
};
Foo.prototype.getName = function () {
    console.log(3);
};
var getName = function () {
    console.log(4);
};
function getName() {
    console.log(5);
}
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

解析:

  • Foo.getName();//2

    • 直接执行输出函数结果为2
  • getName();//4

    • 在预编译过程中,声明变量,函数声明假定义,这时getName变成了输出结果为5的函数
    • 在代码执行阶段,getName赋值成了输出结果为4的函数
  • Foo().getName();//1

    • 函数执行,把getName定义在全局变量下,这是getNmae就变成了输出结果为1的函数
  • getName();//1

    • 这是找全局变量getName为输出的函数
  • new Foo.getName();

    • 先执行Foo.getName(),在实例化。得到的结果为2
  • new Foo().getName();

    • 先执行new Foo()在getName()
    • 得到Foo的实例,在原型链上找getName,及输出结果为3
  • new new Foo().getName();

    • 先执行new Foo()在执行getName(),在实例化整体,及输出结果为3

答案:2 4 1 1 2 3 3