let test={}
test.func=function(){}
如果你此函数是一个构造函数,比如
function animal() {}
let dog = new animal()
dog.move = function () {
console.log('move')
}
这样添加方法后,只有在dog这个实例里面才能访问到move函数
但是你想每个动物都有这个move函数
直接添加到animal()会在初始化实例的时候初始化此move函数,不符合高效的标准
所以都会添加到原型上
在prototype上的方法只会初始化一次,可以提供给所有实例使用,符合节省内存开销的标准
所以一般都会添加到原型对象
像你上面这种情况,test就是一个普通对象,它压根就没有原型:
let Person = {}
Person.age = 29
console.log(Person.prototype) // undefined
你将方法挂在test对象上,那就它就作为test对象的一个普通属性(方法)。
有些场景,你看到的将方法添加到其原型对象上,是为了继承,比如下面的例子:
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function () {
console.log(this.name);
};
let foo = new Person('foo');
let bar= new Person('bar');
foo.sayAge = function () {
console.log(20);
}
foo.sayName(); // foo
foo.sayAge(); // 20
bar.sayName(); // bar
bar.sayAge(); // 报错
上面代码中,Person是一个构造函数,通过在它的prototype上添加一个sayName方法,那么,所有通过Person构造函数产生的对象都会拥有sayName方法(共有)。如果直接添加,比如foo对象上的sayName方法,它只是foo对象才有的。
6 回答5.2k 阅读✓ 已解决
9 回答9.5k 阅读
5 回答3.7k 阅读✓ 已解决
4 回答8.1k 阅读✓ 已解决
7 回答10.1k 阅读
5 回答8.3k 阅读
2 回答10.4k 阅读✓ 已解决
在prototype上添加方法是为了继承方便。你的写法没法将test.func继承给子类。而如果这样写:
let test = function() {
}
和你的代码等价了,子类也可以继承func方法,如:
let subTest = function() {
}
但是这里subTest.func 和 test.func虽然代码完全一致但却是两个不同变量,也就是说js编译后其实将相同代码又复制了一遍;想象一下如果有很多subTest实例,那么func函数就会被复制很多遍造成内存的浪费。而如果func是定义在test的prototype上时:
let test = function() {};
test.prototype.func = function(){};
let subTest = function() {
}
subTest.prototype = new test();
这样形成了原型链,subTest上其实并没有func,但是调用subTest.func()时会沿着原型链向上查找到test.prototype.func。也就是说subTest可以试用func函数,同时又不会再创建一个新的func实例,这样节省了内存开销。
其实js还有很多种继承的实现方式,我这里解释的不是很清楚,如果要更详细的了解可以去看看《js高级程序设计》第6章的内容