构造函数/原型对象/类与继承
一、new关键字
function Person(name) {
this.name = name;
}
Person.prototype = {
constructor: Person,
sayName() {
alert(this.name);
}
};
- 在使用new创建对象时:
- 创建一个新对象,并且这个对象的原型指向构造函数的prototype属性
- 构造函数的this指向这个新对象,执行构造函数
- 返回这个新对象或者构造函数里显式返回的对象
-
假如构造函数显式返回了一个非基础类型的数据,例如一个数组或function,那么构造函数里加的属性和原型上的方法都和这个对象无关。
-
自己实现,期待调用方式为:
const user = create(Person, 'wxm');
function create() {
let[target,...args] = arguments;
if (!target) {
throw new Error('请传入构造函数');
}
const o = Object.create(target.prototype); // 1. 创建空对象并链接原型对象
const v = target.apply(o, args); // 2. 执行构造函数
// 3. 根据构造函数的执行返回值决定返回结果
if (typeof v === 'object' && v !== null) {
return v;
}
return o;
}
二、Object.create 和 new Object
-
const a = Object.create(b)
,创建一个原型对象为b的新对象,此时:a.__proto__ === b
-
可以用
const a = Object.create(null)
来创建一个没有原型的对象,此时a.__proto__ === undefined
-
const a = new Object()
和const a = {}
创建的对象都默认继承自 Object。此时:a.__proto__ === Object.prototype
-
Object.setPrototypeOf()
可以设置对象的原型对象,Object.setPrototypeOf(a, null)
,此时:a.__proto__ === undefined
三、prototype 和 constructor
function Person(name) {
this.name = name;
}
Person.prototype = {
constructor: Person,
sayName() {
alert(this.name);
}
};
prototype和constructor 把构造函数和它的prototype对象关联在一起。
一个实例的原型对象是【它的__proto__
】指向的对象,构造函数的prototype并不是它的原型对象,依然是这个构造函数的__proto__
,不要搞混
-
[].__proto__ === Array.prototype
-
Array.prototype.constructor === Array
-
相当于
[].__proto__.constructor === Array
如果不constructor会怎样?
constructor可以用来检测一个对象是否由某个构造函数创建的。obj.__proto__.constructor
指向创建obj的构造函数,不写constructor就无法从实例上识别出这个对象是由哪个构造函数创建的
[].__proto__.constructor === Array
[].constructor === Array
原型链
Array.prototype.__proto__ === Object.prototype
一个题外话
数组相关方法挂在Array.prototype
对象上,所以数组可以访问到这些方法。 使用const arrayMethods = Object.create(Array.prototype)
创建了一个原型对象为Array.prototype
的空对象,这样就能使用Object.defineProperty去重写对象的value属性,也就是重写这些数组方法,Vue2在做响应式数据时拦截数组方法就用的这种方法
四、继承
- 通过【绑定this为当前对象并执行一遍原构造函数】来继承属性
- 通过【将该构造函数的prototype指向原构造函数的原型对象】来继承方法
// 如果要继承自Person
function Girl() {
Person.apply(this, arguments);
}
const _proto = Object.create(Person.prototype);
_proto.constructor = Girl;
Girl.prototype = _proto;
可以通过Girl.prototype.__proto__.constructor
来得到Person这个构造函数,因为Girl.prototype.__proto__ === Person.prototype