论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提供了方法来读取和判断对象的原型:
// 接前面的例子 |
对象的原型链通常是只读的,用户无法修改某个对象的原型,所以无法修改对象的继承关系。
属性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
构造函数的引用。注意,此属性的值是对函数本身的引用,而不是一个包含函数名称的字符串。对原始类型来说,如1
,true
和"test"
,该值只可读。
详情
所有对象都会从它的原型上继承一个constructor属性:
var o = {}; |
示例:
function Tree(name){ |
小结
大概整理一下js的对象的一些基础概念,
1.每个对象都有[[prototype]]属性,是用来指向自己的原型对象
2.所有对象的[[prototype]]是_proto_,而函数有一个特有的属性是prototype
3.prototype有个属性是constructor指向其原型对象的,可以进行调用。