论js的对象

前言

发现学习node.js的沙盒逃逸时,对象的概念也需要理解一下。

什么是js

js就是javascript,js里面一切皆对象,理解对象是理解js语言的关键

封装、继承、多态

在C++/Java等传统面向对象编程中,类(class)是对象(object)的模板,class不占用内存空间,object占用内存,object也称为class instance,同一个class可以被new出很多个object。

Javascript语言不支持”类”,但Javascript仍然是面向对象语言,面向对象的3要素在JavaScript里都支持:

  • 封装 - 数据与方法封装在一起,方法可以操作数据,这就是JS里的object
  • 继承 - 新创建的对象可以继承父对象的数据和方法,js里有多种方法实现继承,譬如原型方式继承,拷贝继承等
  • 多态 - 一个接口有多种实现

实际上,js里一切皆对象。

什么是对象

js里的对象(object)就是一组键值(name-value)的集合, name总是string类型, value可以是各种类型, 可以是基本数据类型, 可以是数组或其他对象, 也可以是函数, object很像是一个hash map. object里的name-value是无序的。

对象是动态的,可以动态地增加属性和方法。

对象属性

属性特性

每个属性都拥有4个特性,数据属性和访问器属性一共有6种属性特性:

  • 数据属性特有的特性:
    • [[Value]]: 属性的值.
    • [[Writable]]: 控制属性的值是否可以改变.
  • 访问器属性特有的特性:
    • [[Get]]: 存储着getter方法.
    • [[Set]]: 存储着setter方法.
  • 两种属性都有的特性:
    • [[Enumerable]]: 如果一个属性是不可枚举的,则在一些操作下,这个属性是不可见的,比如for…in和Object.keys()
    • [[Configurable]]: 如果一个属性是不可配置的,则该属性的所有特性(除了%%[[Value]]%%)都不可改变

对象的原型[[prototype]]

在js中所有对象都有一个隐含的属性[[prototype]]指向其原型对象,原型对象也有自己的原型,如此下去便形成一个原型链,所有对象的原型链的顶层都是Object.prototype.

请注意,[[prototype]]并不是一个真实的属性名,因此无法通过这个属性名获得原型对象,但js提供了方法来读取和判断对象的原型:

// 接前面的例子
console.log(Object.getPrototypeOf(myFather) === Person.prototype); //true
console.log(Person.prototype.isPrototypeOf(myFather)); //true
console.log(Person.prototype.isPrototypeOf(myMother)); //false

对象的原型链通常是只读的,用户无法修改某个对象的原型,所以无法修改对象的继承关系。

属性proto

在js规范里,对象原型通常是不可见的属性,因此无法直接访问。但某些浏览器里支持__proto__属性,firefox/chrome/safari/nodejs都支持__proto__属性,在这些浏览器里对象原型是可见的,可以直接访问对象的__proto__属性得到对象原型,也可以通过修改对象的__proto__属性来修改对象的原型链。

ECMAScript 6正在讨论把__proto__属性标准化,但目前属性__proto__还不是标准。

本文接下来提到的__proto__, [[prototype]]都是指一个意思,即自身对象里指向其原型对象的属性。

prototype

函数也是对象,所以函数也有属性__proto__,通过字面量声明的函数其原型对象是Function.prototype,当然Function.prototype的原型对象是Object.prototype.

函数还有一个特有的属性prototype,每个函数都有一个prototype属性(特别注意,prototype属性是函数对象特有的属性,不要和js中每个对象到其原型的连接相混淆,那个是隐藏的,只是在firefox/chrome等浏览器中你可以使用__proto__访问到)

constructor
Object.prototype.constructor

返回创建实例对象的 Object 构造函数的引用。注意,此属性的值是对函数本身的引用,而不是一个包含函数名称的字符串。对原始类型来说,如1true"test",该值只可读。

详情

所有对象都会从它的原型上继承一个constructor属性:

var o = {};
o.constructor === Object; // true
示例:
function Tree(name){
this.name=name;
}
var theTree=new Tree("Redwood");
console.log("theTree.constructor is "+the Tree.constructor);
//打印输出
theTree.constructor is function Tree(name) {
this.name = name;
}

小结

大概整理一下js的对象的一些基础概念,
1.每个对象都有[[prototype]]属性,是用来指向自己的原型对象
2.所有对象的[[prototype]]是_proto_,而函数有一个特有的属性是prototype
3.prototype有个属性是constructor指向其原型对象的,可以进行调用。

Author

vague huang

Posted on

2021-07-13

Updated on

2021-07-13

Licensed under

Comments