先抛去此文章的标题(有点晕有木有?),来看下面这段程序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function Star(name,age) {
this.name = name;
this.age = age;
this.sing = function() {
console.log("我会唱歌");
}
}
var ldh = new Star("刘德华",18);
var zxy = new Star("张学友",19);
console.log(ldh.sing === zxy.sing);//false
</script>
</body>
</html>
我们通过打印两者的sing方法可以发现这两个sing指向不同的内存地址。 但是我们不需要修改这个方法啊,每创建个对象就会开辟个内存空间,大大浪费了内存。我们可以让它的对象都共享这个方法,那么就可以节省空间。
prototype原型对象
为此,我们引入了prototype实现对象对该方法的共享
- 每个构造函数都有一个
prototype属性 - 我们可以把那些不变的方法,直接定义在
prototype对象上,这样所有对象的实例就可以共享这些方法 - 一般情况,我们把公共属性定义到构造函数里面,公共的方法我们放到原型对象身上
修改上面的程序:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function Star(name,age) {
this.name = name;
this.age = age;
this.sing = function() {
console.log("我会唱歌");
}
}
var ldh = new Star("刘德华",18);
var zxy = new Star("张学友",19);
Star.prototype.sing = function() {
console.log("我会唱歌");
}
console.log(ldh.sing === zxy.sing);//true
</script>
</body>
</html>
bingo! 这样就实现了方法的共享!
__proto__对象原型
我们来看下面一段程序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function Star(name,age) {
this.name = name;
this.age = age;
}
Star.prototype.sing = function() {
console.log("我会唱歌");
}
var ldh = new Star("刘德华",18);
var zxy = new Star("张学友",19);
console.log(ldh.sing);
</script>
</body>
</html>
诶,我们发现,明明没有给对象添加这个sing方法呀,为啥我们能直接用呢?
其实啊,对象都会有一个属性__proto__指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数的prototype原型对象的属性和方法,就是因为有__proto__原型的存在
通过打印如下代码
console.log(ldh.__proto__ === Star.prototype);//true
说明它们是指向同一块地址空间的,也就是说它们指向的是同一个sing方法
关系图:
__proto__的查找原理
- 首先先看
ldh对象身上有没有sing方法,如果有就执行这个对象上的sing - 如果没有,因为有
__proto__的存在,就去构造函数原型对象prototype身上去查找有没有sing这个方法