之前正在整理问卷平台项目,其中整理到了new这一用法,但发现自己其实对JS对象这一部分并不太熟悉,以及原型链究竟是如何不太清楚,所以便有了这一篇博客的整理,整理内容来自JavaScript权威指南。

对象简介

JavaScript语言是动态的————可以新增属性也可以删除属性————但他们常用来模拟静态对象以及静态类型语言中的”结构体”。有时它们也用做字符串的集合。

对象创建三种方法

对象的创建可以通过三种方法,分别是对象直接量创建,通过new创建,通过Object.create()方法创建。

1.对象直接量

1
2
3
4
var book = {
"title": "javascript",
"author": "张三"
}

如上,便是直接创建对象的方法。

2.通过new创建对象

1
2
3
4
var o = new Object();    //创建一个空对象
var a = new Array(); //创建一个空数组
var d = new Date(); //创建一个表示当前事件的Date对象
var r = new RegExp("js"); //创建一个可以进行模式匹配的对象

上面三种都是通过内置构造函数,还有自定义构造函数,比如

直接使用function构造函数,然后下面通过new来定义变量,下面两个分别为带不带参数以及带两个参数的构造

另外,值得一提的是__proto__属性,该属性是用于查询/设置对象的原型,但是似乎并不支持IE和Opera(此处并未测试),所以不建议使用,点开后会发现有一个constructor属性,指代其构造函数,如下图所示,但是此处并未理解透彻,需待以后深入理解。

3.Object.create()方法创建

第一个参数是这个对象的原型,第二个可选参数是对对象属性的进一步描述,例如

__proto__是其继承的原型,可以看到第一层__proto__继承的是{x:1,y:2},然后第二层__proto__继承的是Object原型。

不可变原始值和可变的对象引用

原始值(undefined、null、布尔值、数字、字符串),对象(包括数组和函数),原始值是不可更改的,而对象则不同

不可变原始值

可以看到原始值不可更改

可变的对象引用

然而对象引用却可变

可以看到当另b=a.p的时候相当于将b指向了a.p,那么这个时候两个变量指向的就是同一个值,这时候为b.x赋值,那么a.p.x同样会被改变,这就是对象引用的可变。那么如果我们不想这样该怎么办呢,可以逐一赋值,比如说

直接对c的属性x进行赋值,这时候就不会将c指向a.p,这时候改变c.x就不会改变a.p.x

对象属性特性

  • 可写,表明是否可以设置该属性的值
  • 可枚举,表明是否可以通过for/in循环返回该属性
  • 可配置,表明是否可以通过删除或修改属性

对象检测属性

检测对象里面包含的属性,可使用inhasOwnPropertypropertyIsEnumerable方法来完成该工作。

in
hasOwnPreperty
propertyIsEnumerable

三者之间区别

in自有属性和继承属性都能返回true,hasOwnPreperty自有属性返回ture,继承属性返回false,propertyIsEnumerable自有属性为可枚举时才返回true,是hasOwnpreperty的增强版

getter和setter

由getter和setter属性定义的属性称作“存储器属性”,不同于“数据属性”,当调用getter方法时,返回值就是属性表达式的值,当程序设置一个存取器属性的值时,将调用setter方法,将右侧的值当作参数传入setter。如果属性同时具有getter和setter方法,那么他是一个读/写属性,如果只有getter则是只读。只有setter则是只写,读取数据将返回undefined。

getter和setter的枚举

这里假如说定义一个get r()或定义一个set r(),那么这个r也是可枚举的,也就是说可以通过for/in循环来遍历到。

那么修改一下可枚举性

可以看到通过for/in循环并没有循环到属性r,也就是说可以通过设置属性的可枚举性来控制是否由for/in循环到。

继承下的for/in循环

同时,可以通过继承来达到for/in循环的遍历效果

可以看到for/in循环循环到了xyr,倘若这时候设置其原型a的某个属性的可枚举型为false,那么也会受到影响。

实例

如上图是一个定义getter和setter的实例,注意,theta只有getter方法,没有setter方法,所以是只读的,下面进行测试

可以看出上图,都获取到了相应的值

对比看出,对r的修改成功了,而对theta的修改并没有成功。

通过getOwnPropertyDescriptor()方法获得属性描述

  • value: 值
  • writable: 可写性
  • enumerable: 可枚举性
  • configurable: 可配置性

通过definePeoperty()方法修改属性描述

可通过该方法修改或直接添加数据属性

上面即通过definePeoperty添加的一个x数据以及修改的属性

总结

本来这次想把原型链也顺带整理一下,结果发现这也是一块比较复杂的东西,所以决定详细学习一下类的使用继承方法等内容之后再来详细整理一下类和模块以及原型链的内容。