- 每个“构造函数”中都有一个默认的属性,叫prototype
prototype属性保存着一个对象,这个对象我们称之为"原型对象"
<script>
function Person(name, age) {
this.name = name;
this.age = age;
}
let obj1 = new Person("zs", 20);
console.log(Person.prototype);
</script>
控制台输出:
- 每个“原型对象”中都有一个默认的属性,叫constructor,
constructor 指向当前原型对象对应的那个“构造函数
<script>
function Person(name, age) {
this.name = name;
this.age = age;
}
let obj1 = new Person("zs", 20);
console.log(Person.prototype.constructor);
</script>
控制台输出:
- 通过构造函数创建出来的对象我们称之为"实例对象",每个"实例对象"中都有一个默认的属性,叫做__proto__ , __proto__指向创建它的那个构造函数的"原型对象"
<script>
function Person(name, age) {
this.name = name;
this.age = age;
}
let obj1 = new Person("zs", 20);
console.log(obj1.__proto__);
</script>
控制台输出:
三者关系图:
4.JavaScript中函数是引用类型(对象类型),既然是对象,所以也是通过构造函数创建出来的,“所有函数”都是通过Function构造函数创建出来的对象
<script>
console.log(Function);
</script>
控制台输出(说明存在Function构造函数):
5.JavaScript中只要是“函数”就要prototype属性
<script>
console.log(Function.prototype);
</script>
控制台输出:
6.JavaScript中只要“原型对象”就有constructor属性,“Function“原型对象”的constructor指向它对应的构造函数
<script>
function Person(name, age) {
this.name = name;
this.age = age;
}
let obj1 = new Person("zs", 20);
console.log(Function.prototype.constructor);
console.log(Function.prototype.constructor === Function); //说明Function原型对象”的constructor指向它对应的构造函数
console.log(Person.__proto__ === Function.prototype); //说明实例对象指向它的原型对象
console.log(Function.__proto__ === Function.prototype); //说明Function的__proto__指向它的原型对象
</script>
控制台输出
关系图:
7.Object函数
在JavaScript中,有一个默认的函数名为Object,同样是通过构造函数Function创建出来的
先来看看Object有啥属性
<script>
console.log(Object);
console.log(Object.prototype);
console.log(Object.__proto__);
console.log(Object.constructor);
</script>
控制台输出:
关键:原型对象也是个对象,也有__proto__ 且__proto__ 指向null
<script>
// Object 是 Function的实例对象,故Object的__proto__指向的是Function的原型对象
console.log(Object.__proto__ === Function.prototype);
// Object是构造函数,有prototype属性 一个原型对象的constructor指向它的构造函数
console.log(Object.prototype.constructor === Object);
//原型对象也是个对象,也有__proto__
console.log(Object.prototype.__proto__);
</script>
控制台输出:
关系图:
函数对象完整关系图:(重点)
原型链:
JavaScript中的原型链是根据以上的图进行查找,当实例对象的__proto__找不到时,就他的原型对象里找,还是找不到就会去Object中原型对象找,还没有就输出null
情况1:实例对象的__proto__已经定义
<script>
function Person(name, age) {
this.name = name;
this.age = age;
this.type = '构造函数中的人';
this.say = function() {
console.log("构造函数中的Hello World");
}
}
Person.prototype = {
type: '人',
say: function() {
console.log("Hello World");
}
}
let obj1 = new Person("zs", 20);
let obj2 = new Person("ls", 25);
console.log(obj1);
obj1.say();
console.log(obj1.type);
</script>
控制台输出:
情况2:实例对象的__proto__没有定义,而他的原型对象Person.prototype已经定义
<script>
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
type: '人',
say: function() {
console.log("Hello World");
}
}
let obj1 = new Person("zs", 20);
let obj2 = new Person("ls", 25);
console.log(obj1);
obj1.say();
console.log(obj1.type);
</script>
控制台输出:
优化建议:
<script>
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
type: '人',
say: function() {
console.log("Hello World");
}
}
console.log(Person.prototype.constructor);
</script>
控制台输出:
由以上可知,Person的原生对象指向了Object而不是Person,如何优化呢,只需手动修改 constructor属性即可
<script>
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
constructor: Person,
type: '人',
say: function() {
console.log("Hello World");
}
}
console.log(Person.prototype.constructor);
</script>
控制台输出:
总结点:
(1)Function函数是所有函数的祖先函数
(2)所有构造函数都有一个prototype属性
(3)所有原型对象都有一个constructor属性
(4)所有函数都是对象
(5)所有对象都有一个__proto__属性