通过上面的讲解,大家应该明白了如何创建一个构造函数,但是,那样创建的构造函数有一个问题。
那就是:每次我们new这个函数时它就会在内存中创建出一个副本,每个副本都存储在不同的内存空间中,也就是说:多次new同一个构造函数,得到的实例对象是完全不同的多个实例对象。
举例来说明一下:
<!DOCTYPE html>
<html>
<head>
<title>面向对象(二) 构造函数的原型对象</title>
</head>
<body>
<script type="text/javascript">
function Person(n, a){
this.name = n;
this.age = a;
this.say = function(){
console.log('我叫' + this.name);
}
}
var person1 = new Person('tom',33);
var person2 = new Person('tom',33);
console.log(person1==person2);
</script>
</body>
</html>
通过以上代码可以看到,即使我们new的时候给构造函数传入相同的参数,两次new出来的实例对象都是完全不同的两个东西。
也就是说:如果我们用一个循环重复执行new都能把内存给占满了,这是一件可怕的事情。
所以,在JS官方没有给出解决方法之前,民间是这样做的
<!DOCTYPE html>
<html>
<head>
<title>面向对象(二) 构造函数的原型对象</title>
</head>
<body>
<script type="text/javascript">
var fn = function(){
console.log('我叫' + this.name);
};
function Person(n, a){
this.name = n;
this.age = a;
this.say = fn;
}
var person1 = new Person('张三', 30);
var person2 = new Person('李四', 40);
console.log(person1);
console.log(person2);
</script>
</body>
</html>
以上代码中,我们把构造函数中的方法写到构造函数外面,在构造函数中把外面的函数名赋值给构造函数的方法。
由于普通函数仅在内存的堆空间中存储一份,而且构造函数的的属性占用的栈空间极小,所以这就解决了内存浪费的问题。
但是,这依然存在一个问题,如果一个构造函数的方法特别多,而且我们还有很多构造函数,这样写的话命名是个问题,弄不好就命名冲突了。
所以,民间又想出这样一个办法
<!DOCTYPE html>
<html>
<head>
<title>面向对象(二) 构造函数的原型对象</title>
</head>
<body>
<script type="text/javascript">
var obj = {
"fn":function(){
console.log('我叫' + this.name);
},
"fn2":function(){
console.log('我走的很快');
}
};
//构造函数中,给每个人直接定义方法(从公共对象中取)
function Person(n, a){
this.name = n;
this.age = a;
this.say = obj.fn;
this.walk = obj.fn2;
}
</script>
</body>
</html>
以上代码中,我们把构造函数的所有方法写到外部的一个字面量对象中,这样就隔离了公用空间。如果是多个构造函数,我们就在外部定义多个字面量对象,分别存放每个构造函数的方法。
然后将外部对象中的方法赋值个构造函数的方法。
这样做似乎比较完美了,但是毕竟是民间的,实现起来有点麻烦。
此时JS官方终于给出一个解决方案,那就是构造函数的原型对象,即构造函数.prototype所指向的对象,这个prototype相当于民间的外部字面量对象名称。
请看下面的代码
<!DOCTYPE html>
<html>
<head>
<title>面向对象(二) 构造函数的原型对象</title>
</head>
<body>
<script type="text/javascript">
function Person(n, a){
this.name = n;
this.age = a;
}
Person.prototype.say=function(){
console.log('我走的很快');
};
var person=new Person('tom',33);
person.say();
</script>
</body>
</html>
实例对象同样正常使用了say方法。
所以,再次重复,构造函数.prototype就是构造函数的原型对象,请不要嫌我啰嗦,因为即使我不停的重复,讲着讲着可能很多人就分不清楚了。
本节就先讲到这里,请大家务必认真理解以上内容后再继续下面的学习。
|