函数的原型(prototype)
- 每个函数都有一个prototype属性,它默认指向一个Object 空对象(称为原型对象)
- 原型对象中有一个属性constructor,它指向函数对象
构造器属性
每个函数都有 "prototype"
属性,即使我们没有提供它。
默认的 "prototype"
是一个只有属性 constructor
的对象,属性 constructor
指向函数自身。
像这样:
function Rabbit() {}
/* default prototype
Rabbit.prototype = { constructor: Rabbit };
*/
我们可以检查一下:
function Rabbit() {}
// by default:
// Rabbit.prototype = { constructor: Rabbit }
alert( Rabbit.prototype.constructor == Rabbit ); // true
通常,如果我们什么都不做,constructor
属性可以通过 [[Prototype]]
给所有 rabbits 使用:
function Rabbit() {}
// by default:
// Rabbit.prototype = { constructor: Rabbit }
let rabbit = new Rabbit(); // inherits from {constructor: Rabbit}
alert(rabbit.constructor == Rabbit); // true (from prototype)
我们可以使用 constructor
属性来创建一个新对象,该对象使用与现有对象相同的构造器。
像这样:
function Rabbit(name) {
this.name = name;
alert(name);
}
let rabbit = new Rabbit("White Rabbit");
let rabbit2 = new rabbit.constructor("Black Rabbit");
当我们有一个对象,但不知道它使用了哪个构造器(例如它来自第三方库),并且我们需要创建另一个类似的对象时,用这种方法就很方便。
但是,关于 "constructor"
最重要的是……
……JavaScript 自身并不能确保正确的 "constructor"
函数值。
是的,它存在于函数的默认 "prototype"
中,但仅此而已。之后会发生什么 —— 完全取决于我们。
特别是,如果我们将整个默认 prototype 替换掉,那么其中就不会有 "constructor"
了。
例如:
function Rabbit() {}
Rabbit.prototype = {
jumps: true
};
let rabbit = new Rabbit();
alert(rabbit.constructor === Rabbit); // false
因此,为了确保正确的 "constructor"
,我们可以选择添加/删除属性到默认 "prototype"
,而不是将其整个覆盖:
function Rabbit() {}
// 不要将 Rabbit.prototype 整个覆盖
// 可以向其中添加内容
Rabbit.prototype.jumps = true
// 默认的 Rabbit.prototype.constructor 被保留了下来
或者,也可以手动重新创建 constructor
属性:
Rabbit.prototype = {
jumps: true,
constructor: Rabbit
};
// 这样的 constructor 也是正确的,因为我们手动添加了它
给原型对象添加属性(一般都是方法)
-
作用:它的所有实例对象自动拥有原型对象的方法
(实例对象可以访问到)
1、读取对象的属性值时,会自动到原型链中找
2、设置对象属性值时,不会查找原型链,如果当前对象没有此属性,直接添加此属性并设置值
3、方法一般定义在原型中,属性一般通过构造函数定义在对象本身上
显式原型 / 隐式原型
1、 每个函数function都有一个prototype,即显式原型(属性)
2、 每个实例对象都有一个____proto____ ,即称为隐式原型(属性)
3、 对象的隐式原型的值等于对应构造函数的显式原型的值
function Person(){
this.dog = 'sss'
}
const p = new Person()
console.log(p.__proto__); // { constructor: f Person() }
console.log(Person.prototype); // { constructor: f Person() }
// 即 p实例对象的 隐式原型__proto__ == Person构造函数的 显示原型 prototype
4、总结:
- 函数的prototype属性:在定义函数时自动添加的,默认值一个空的Object对象
- 实例对象的
__proto__
属性:创建对象时自动添加的,默认值是其构造函数的prototype属性值
原型链
1、函数的显式原型指向的对象默认式空Object对象(object除外)
2、所有函数都是Function的实例(包含它自己)
3、Object的原型对象是原型链的尽头