Skip to main content

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 文档有详细记录

对象名称类型
AggregateErrorThe constructor
ArrayThe Array constructor
ArrayBufferThe ArrayBuffer constructor
BigIntThe BigInt constructor
BigInt64ArrayThe BigInt64Array constructor
BigUint64ArrayThe BigUint64Array constructor
BooleanThe Boolean constructor
DataViewThe DataView constructor
DateThe Date constructor
ErrorThe Error constructor
EvalErrorThe EvalError constructor
FinalizationRegistryThe FinalizationRegistry constructor
Float32ArrayThe Float32Array constructor
Float64ArrayThe Float64Array constructor
FunctionThe Function constructor
Int8ArrayThe Int8Array constructor
Int16ArrayThe Int16Array constructor
Int32ArrayThe Int32Array constructor
MapThe Map constructor
NumberThe Number constructor
ObjectThe Object constructor
PromiseThe Promise constructor
ProxyThe Proxy constructor
RangeErrorThe RangeError constructor
ReferenceErrorThe ReferenceError constructor
RegExpThe RegExp constructor
SetThe Set constructor
SharedArrayBufferThe SharedArrayBuffer constructor
StringThe String constructor
SymbolThe Symbol constructor
SyntaxErrorThe SyntaxError constructor
TypeErrorThe TypeError constructor
Uint8ArrayThe Uint8Array constructor
Uint8ClampedArrayThe Uint8ClampedArray constructor
Uint16ArrayThe Uint16Array constructor
Uint32ArrayThe Uint32Array constructor
URIErrorThe URIError constructor
WeakMapThe WeakMap constructor
WeakRefThe WeakRef constructor
WeakSetThe 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)