ECMAScript 对象
ECMAScript 是一种基于对象的编程语言,其中对象是一组零个或多个属性的集合。ECMAScript 程序可以看作是一组相互通信的对象。
对象的创建
- 通过字面符号创建
let person = {
name: "Alice",
age: 18,
};
- 通过构造函数(创建和初始化对象的函数),然后执行初始化代码,为它们的属性分配初始值
function Person(name, age) {
this.name = name;
this.age = age;
}; // 构造函数 Person
let person = new Person("Alice",18);
字面符号也是通过构造函数实现的
let person = new Object(); // 构造函数 Object
person.name = "Alice";
person.age = 18;
几乎所有的对象都有一个构造函数,除了使用 Object.create(null) 创建的对象。
Object.create(null) 并不会创建 Object.prototype 这个委托。所以它比{}更空。
console.log(Object); // ƒ Object() { [native code] }
console.log(Array); // ƒ Array() { [native code] }
console.log(Function); // ƒ Function() { [native code] }
console.log(Object.create(null)); // {}
[native code] 意味着这是一个原生的内置函数,它们是由宿主引擎实现的,而不是由 ECMAScript 代码定义的。这些对象又叫做内置对象(Built-in Objects)。
这些内置对象有多少呢,ECMAScript 文档有详细记录
| 对象名称 | 类型 |
|---|---|
| AggregateError | The constructor |
| Array | The Array constructor |
| ArrayBuffer | The ArrayBuffer constructor |
| BigInt | The BigInt constructor |
| BigInt64Array | The BigInt64Array constructor |
| BigUint64Array | The BigUint64Array constructor |
| Boolean | The Boolean constructor |
| DataView | The DataView constructor |
| Date | The Date constructor |
| Error | The Error constructor |
| EvalError | The EvalError constructor |
| FinalizationRegistry | The FinalizationRegistry constructor |
| Float32Array | The Float32Array constructor |
| Float64Array | The Float64Array constructor |
| Function | The Function constructor |
| Int8Array | The Int8Array constructor |
| Int16Array | The Int16Array constructor |
| Int32Array | The Int32Array constructor |
| Map | The Map constructor |
| Number | The Number constructor |
| Object | The Object constructor |
| Promise | The Promise constructor |
| Proxy | The Proxy constructor |
| RangeError | The RangeError constructor |
| ReferenceError | The ReferenceError constructor |
| RegExp | The RegExp constructor |
| Set | The Set constructor |
| SharedArrayBuffer | The SharedArrayBuffer constructor |
| String | The String constructor |
| Symbol | The Symbol constructor |
| SyntaxError | The SyntaxError constructor |
| TypeError | The TypeError constructor |
| Uint8Array | The Uint8Array constructor |
| Uint8ClampedArray | The Uint8ClampedArray constructor |
| Uint16Array | The Uint16Array constructor |
| Uint32Array | The Uint32Array constructor |
| URIError | The URIError constructor |
| WeakMap | The WeakMap constructor |
| WeakRef | The WeakRef constructor |
| WeakSet | The WeakSet constructor |
如果不使用 new 关键字,而直接调用构造函数,会导致意想不到的结果。
new Date(2009, 11); // 将创建一个新的Date对象
Date(2009, 11) ; // 将会产生当前时间的字符串,而且不是一个对象
构造函数
构造函数是创建和初始化对象的函数,是函数的一种。
每个构造函数都是一个带有名为 prototype(原型) 属性的函数,用于实现基于原型的继承和共享属性。
构造函数创建的每个对象都有对构造函数的 prototype 属性的隐式引用 __proto__(指向原型)。
prototype是构造函数的属性(函数专属)。__proto__是实例对象的属性(对象专属)。
function Fn() {};
const fn = new Fn();
Fn.prototype === fn.__proto__; // 输出:true
内置对象的继承
绝大多数内置对象都是继承自 object 对象(除了 object 对象),而最终的原型 Object.prototype 没有再继承其它对象,它的 __proto__ 属性指向 null。
Array.prototype.__proto__ === Object.prototype // 输出:true
Function.prototype.__proto__ === Object.prototype // 输出:true
console.log(Object.prototype.__proto__); // 输出:null
原型链
这种继承方式,使得我们操作实例对象的属性和方法时,首先在实例对象自身查找是否存在对应的私有属性或私有方法,找到了,则查找结束,直接使用该属性或方法。
如果在实例对象上未找到对应的属性或方法,则会基于 __proto__ 属性向上查找,找到所属构造函数的 prototype,继续在构造函数的 prototype 上查找是否存在对应的属性或方法。如果找到了,则查找结束,直接使用该属性或方法。
如果在构造函数的 prototype 上仍未找到对应的属性或方法,则会继续基于 __proto__ 属性一直向上查找,直到找到最终原型,即 Object.prototype。如果在 Object.prototype 上仍未找到对应的属性或方法,则返回 undefined,如果将 undefined 当作方法执行,就会报错。
当声明一个 object 变量 obj 时,它的原型链是这样的
let obj = {};
obj.__proto__ -> Object
Object.__proto__ -> null
当声明一个 Array 变量 arr 时,它的原型链是这样的
let arr = [];
arr.__proto__ -> Array
Array.__proto__ -> Object
Object.__proto__ -> null
当声明一个 Funtion 变量 fn 时,它的原型链是这样的
function fn() {};
fn.__proto__ -> Function
Function.__proto__ -> Object
Object.__proto__ -> null
继承
- 原型继承
B.prototype = new A()
- Call继承
function B(){
A.call(this);
}
new B() // 修改this,然后执行A函数,实现了继承
- 寄生组合继承
B.prototype = Object.create(A.prototype)
- Class继承
class Fn{
constructor(n.m)
super();
this.x = n;
this.y = m;
}
let f = new Fn(10,20)