constructor:保存自己构造函数引用的属性
1.可以通过对象.constructor
拿到创建该实例对象的构造函数。
2.对象由函数创建,函数都是Function对象实例。
function Person() {...}
console.log(Person.constructor) // 输出结果:[Function: Function]
console.log(Function.constructor) // 输出结果:[Function: Function]
console.log(Object.constructor) // 输出结果:[Function: Function]
prototype对象:用于放某同一类型实例的共享属性和方法,实质上是为了内存着想。
1.原型对象就是实例对象自己构造函数内的prototype对象。
2.
function Person() {...}
let person1 = new Person();
let person2 = new Person();
现在我们想给Person类的实例对象(person1、person2)添加效果相同的方法:
person1.sayHello = function() {
console.log('Hello!')
}
person2.sayHello = function() {
console.log('Hello!')
}
console.log(person1.sayHello === person2.sayHello) // false,它们不是同一个方法,各自占有内存
如果这时候有千千万万个实例对象,上面的添加方法代码冗余 且会占用很多内存,没有必要,于是prototype就出来解决这个问题了。当需要为大量实例添加相同效果的方法时,可以将方法存放在prototype对象中,并将该prototype对象放在这些实例的构造函数上,达到共享、公用的效果。
Person.prototype.sayHello = function() {
console.log('Hello!')
}
console.log(person1.sayHello === person2.sayHello) // true,同一个方法
3.new Person( )出来的千千万万个实例中如果都有constructor属性,并且都指向创建自己的构造函数,那岂不又出现了上述问题:实例对象们都拥有一个效果相同但却都各自占用一部分内存的属性?所以实例对象的constructor属性被当做共享属性放在原型对象(prototype对象)中,prototype对象放在这些实例的构造函数上
proto
1.前面我们讲的内容可以用下面这个图来表示:我们发现一个问题:有的时候我们需要更改共享方法(prototype对象中的方法)这个时候就需要得到prototype 但是你看下面的图 你怎么得到prototype对象呢?
此时__proto__应运而生,每个实例对象都有一个__proto__属性,指向构造函数的prototype对象:
- 实例对象.__ proto__ = 创建自己的构造函数内部的prototype(原型对象)
- 实例对象.__ proto__.constructor = 创建自己的构造函数
2.实例对象.constructor 等于 实例对象.__ proto__.constructor?
是的。当在一个实例对象上找不到某个属性时,JS就会去它的原型对象上找是否有相关的共享属性或方法
3.prototype也是个对象,它肯定也有个__proto__指向他的构造函数的原型对象
function Person() {...}
let person1 = new Person();
以上代码的指向如图所示:
由此可见:
(1)所有函数的__proto__指向Function函数的prototype对象
(2)Object函数是所有对象通过原型链追溯到最根的构造函数。
(3)Object函数的prototype中的__proto__指向null:为什么Object函数不能像Function函数一样让__proto__属性指向自己的prototype?如果指向自己的prototype,那当找不到某一属性时沿着原型链寻找的时候就会进入死循环,所以必须指向null
原型链
左边的图:Function函数因为是个特殊的例子,它的构造函数就是自己,所以__proto__属性也指向自己的prototype对象;但它的特殊性并不影响它的prototype对象依然不出意外的是Object函数的实例
右边的图:这个理解起来就很难受,因为Object函数和别的函数一样也是Function函数的实例,所以它的__proto__属性毫无例外地是指向Function函数的prototype对象,但是问题是Function函数中的prototype本身又是Object函数的实例对象,所以Function函数中的prototype对象中的__proto__属性就指向Object函数的prototype对象