对象原型 _ _proto_ _(看三遍以上)
每一个实例化对象自己内部,都有一个_ _proto_ _,用来指向我们构造函数的原型对象prototype
```javascript
function Star(uname, age) {
this.uname = uname;
this.age = age;
// this.sing = function() {
// console.log('我会唱歌');
// }
}
Star.prototype.sing = function() {
console.log('我会唱歌');
}
var ldh = new Star('刘德华', 18);
var dlj = new Star('邓丽君', 32);
// true: 证明是指向同一个地址:构造函数的原型对象的sing方法
console.log(ldh.sing === dlj.sing); // true
// true: 实例对象的原型 和 构造函数的原型对象 指向同一地址
console.log(ldh.__proto__ === Star.prototype);
```
一、实例对象查找方法sing()的顺序:
1、首先在ldh对象身上(即构造函数内部)查找sing()方法,如果找到就执行它;
2、如果没有,再通过自身(即实例对象)的_ _proto_ _属性,去构造函数的原型对象prototype里查找sing()方法,同时这也解决了为什么实例对象ldh可以访问到构造函数的原型对象的疑问。
二、每个实例对象都会有一个属性_ _proto_ _:
它指向构造函数的prototype原型对象,之所以我们的实例对象可以使用构造函数prototype原型对象的属性和方法ldh.sing(),就是因为对象有_ _proto_ _原型的存在。
1、_ _proto_ _对象原型 和 prototype原型对象 是等价的,指向同一地址
2、_ _proto_ _对象原型 存在意义是为对象提供一个查找方向,但它是非标属性,实际开发中是不可以使用的属性,它只是内部指向原型对象prototype.
原型constructor构造函数
```javascript
function Star(uname, age) {
this.uname = uname;
this.age = age;
// this.sing = function() {
// console.log('我会唱歌');
// }
}
Star.prototype.sing = function() {
console.log('我会唱歌');
}
var ldh = new Star('刘德华', 18);
var dlj = new Star('邓丽君', 32);
console.log(ldh.__proto__);
console.log(Star.prototype);
console.log(ldh.__proto__.constructor);
console.log(Star.prototype.constructor);
```
结果如下:
_ _proto_ _对象原型 和 构造函数的prototype原型对象 里面都有一个属性constructor ,constructor我们称为构造函数,因为它指回构造函数本身。constructor主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。
```javascript
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
// Star.prototype.sing = function() {
// console.log('我会唱歌');
// };
// Star.prototype.movie = function() {
// console.log('我会演电影');
// }
// 如果方法有多,我们将上面方法以对象形式赋值的,整理如下:
Star.prototype = {
sing: function() {
console.log('我会唱歌');
},
movie: function() {
console.log('我会演电影');
}
}
var ldh = new Star('刘德华', 18);
var dlj = new Star('邓丽君', 32);
console.log(ldh.__proto__);
console.log(Star.prototype);
console.log(ldh.__proto__.constructor);
console.log(Star.prototype.constructor);
```
看看左边是重写Star.prototype = { } 后结果,右边没有重写,而是在原型中添加方法Star.prototype.sing = function(){ } ,两者结果对比。
因为对Star的构造函数原型重写,使原型中的指回constructor消失
所以我们要重新指回
```javascript
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
// 如果方法有多,我们将上面方法以对象形式赋值的,整理如下:
Star.prototype = {
// 利用constructor手动指回,原来构造函数
constructor: Star,
sing: function() {
console.log('我会唱歌');
},
movie: function() {
console.log('我会演电影');
}
}
var ldh = new Star('刘德华', 18);
var dlj = new Star('邓丽君', 32);
console.log(ldh.__proto__);
console.log(Star.prototype);
console.log(ldh.__proto__.constructor);
console.log(Star.prototype.constructor);
```
看结果,重新指回构造函数
构造函数、实例、原型对象三者之间的关系
1、构造函数 通过 Star.prototype 指向 原型对象;
2、原型对象 通过 Star.prototype.constructor 指向 构造函数;
3、ldh对象实例 通过 ldh._ _proto_ _指向 原型对象;
再通过 原型对象的constructor,要写成ldh._ _proto_ _constructor,指回 构造函数;