深入理解JavaScript系列(18):面向对象编程之E(2)


var foo = {x: 10};
 
// 添加新属性
foo.y = 20;
console.log(foo); // {x: 10, y: 20}
 
// 将属性值修改为函数
foo.x = function () {
  console.log('foo.x');
};
 
foo.x(); // 'foo.x'
 
// 删除属性
delete foo.x;
console.log(foo); // {y: 20}

有些属性不能被修改——(只读属性、已删除属性或不可配置的属性)。 我们将稍后在属性特性里讲解。

另外,ES5规范规定,静态对象不能扩展新的属性,并且它的属性页不能删除或者修改。他们是所谓的冻结对象,可以通过应用Object.freeze(o)方法得到。

复制代码 代码如下:


var foo = {x: 10};
 
// 冻结对象
Object.freeze(foo);
console.log(Object.isFrozen(foo)); // true
 
// 不能修改
foo.x = 100;
 
// 不能扩展
foo.y = 200;
 
// 不能删除
delete foo.x;
 
console.log(foo); // {x: 10}

在ES5规范里,也使用Object.preventExtensions(o)方法防止扩展,或者使用Object.defineProperty(o)方法来定义属性:

复制代码 代码如下:


var foo = {x : 10};
 
Object.defineProperty(foo, "y", {
  value: 20,
  writable: false, // 只读
  configurable: false // 不可配置
});
 
// 不能修改
foo.y = 200;
 
// 不能删除
delete foo.y; // false
 
// 防治扩展
Object.preventExtensions(foo);
console.log(Object.isExtensible(foo)); // false
 
// 不能添加新属性
foo.z = 30;
 
console.log(foo); {x: 10, y: 20}

内置对象、原生对象及宿主对象

有必要需要注意的是规范还区分了这内置对象、元素对象和宿主对象。

内置对象和元素对象是被ECMAScript规范定义和实现的,两者之间的差异微不足道。所有ECMAScript实现的对象都是原生对象(其中一些是内置对象、一些在程序执行的时候创建,例如用户自定义对象)。内置对象是原生对象的一个子集、是在程序开始之前内置到ECMAScript里的(例如,parseInt, Match等)。所有的宿主对象是由宿主环境提供的,通常是浏览器,并可能包括如window、alert等。

注意,宿主对象可能是ES自身实现的,完全符合规范的语义。从这点来说,他们能称为“原生宿主”对象(尽快很理论),不过规范没有定义“原生宿主”对象的概念。

Boolean,String和Number对象

另外,规范也定义了一些原生的特殊包装类,这些对象是:

1.布尔对象
2.字符串对象
3.数字对象

这些对象的创建,是通过相应的内置构造器创建,并且包含原生值作为其内部属性,这些对象可以转换省原始值,反之亦然。

复制代码 代码如下:


var c = new Boolean(true);
var d = new String('test');
var e = new Number(10);
 
// 转换成原始值
// 使用不带new关键字的函数
с = Boolean(c);
d = String(d);
e = Number(e);
 
// 重新转换成对象
с = Object(c);
d = Object(d);
e = Object(e);

此外,也有对象是由特殊的内置构造函数创建: Function(函数对象构造器)、Array(数组构造器) RegExp(正则表达式构造器)、Math(数学模块)、 Date(日期的构造器)等等,这些对象也是Object对象类型的值,他们彼此的区别是由内部属性管理的,我们在下面讨论这些内容。

字面量Literal

对于三个对象的值:对象(object),数组(array)和正则表达式(regular expression),他们分别有简写的标示符称为:对象初始化器、数组初始化器、和正则表达式初始化器:

复制代码 代码如下:


// 等价于new Array(1, 2, 3);
// 或者array = new Array();
// array[0] = 1;
// array[1] = 2;
// array[2] = 3;
var array = [1, 2, 3];
 
// 等价于
// var object = new Object();
// object.a = 1;
// object.b = 2;
// object.c = 3;
var object = {a: 1, b: 2, c: 3};
 
// 等价于new RegExp("^\\d+$", "g")
var re = /^\d+$/g;

注意,如果上述三个对象进行重新赋值名称到新的类型上的话,那随后的实现语义就是按照新赋值的类型来使用,例如在当前的Rhino和老版本SpiderMonkey 1.7的实现上,会成功以new关键字的构造器来创建对象,但有些实现(当前Spider/TraceMonkey)字面量的语义在类型改变以后却不一定改变。

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgfgzd.html