关于调用内置构造函数,使用还是不适用new操作符没有通用规则,取决于构造函数。 例如Array或Function当使用new操作符的构造函数或者不使用new操作符的简单函数使用产生相同的结果的:
复制代码 代码如下:
var a = Array(1, 2, 3); // [object Array]
var b = new Array(1, 2, 3); // [object Array]
var c = [1, 2, 3]; // [object Array]
var d = Function(''); // [object Function]
var e = new Function(''); // [object Function]
有些操作符使用的时候,也有一些显示和隐式转化:
复制代码 代码如下:
var a = 1;
var b = 2;
// 隐式
var c = a + b; // 3, number
var d = a + b + '5' // "35", string
// 显式
var e = '10'; // "10", string
var f = +e; // 10, number
var g = parseInt(e, 10); // 10, number
// 等等
属性的特性
所有的属性(property) 都可以有很多特性(attributes)。
1.{ReadOnly}——忽略向属性赋值的写操作尝,但只读属性可以由宿主环境行为改变——也就是说不是“恒定值” ;
2.{DontEnum}——属性不能被for..in循环枚举
3.{DontDelete}——糊了delete操作符的行为被忽略(即删不掉);
4.{Internal}——内部属性,没有名字(仅在实现层面使用),ECMAScript里无法访问这样的属性。
注意,在ES5里{ReadOnly},{DontEnum}和{DontDelete}被重新命名为[[Writable]],[[Enumerable]]和[[Configurable]],可以手工通过Object.defineProperty或类似的方法来管理这些属性。
复制代码 代码如下:
var foo = {};
Object.defineProperty(foo, "x", {
value: 10,
writable: true, // 即{ReadOnly} = false
enumerable: false, // 即{DontEnum} = true
configurable: true // 即{DontDelete} = false
});
console.log(foo.x); // 10
// 通过descriptor获取特性集attributes
var desc = Object.getOwnPropertyDescriptor(foo, "x");
console.log(desc.enumerable); // false
console.log(desc.writable); // true
// 等等
内部属性和方法
对象也可以有内部属性(实现层面的一部分),并且ECMAScript程序无法直接访问(但是下面我们将看到,一些实现允许访问一些这样的属性)。 这些属性通过嵌套的中括号[[ ]]进行访问。我们来看其中的一些,这些属性的描述可以到规范里查阅到。
每个对象都应该实现如下内部属性和方法:
1.[[Prototype]]——对象的原型(将在下面详细介绍)
2.[[Class]]——字符串对象的一种表示(例如,Object Array ,Function Object,Function等);用来区分对象
3.[[Get]]——获得属性值的方法
4.[[Put]]——设置属性值的方法
5.[[CanPut]]——检查属性是否可写
6.[[HasProperty]]——检查对象是否已经拥有该属性
7.[[Delete]]——从对象删除该属性
8.[[DefaultValue]]返回对象对于的原始值(调用valueOf方法,某些对象可能会抛出TypeError异常)。
通过Object.prototype.toString()方法可以间接得到内部属性[[Class]]的值,该方法应该返回下列字符串: "[object " + [[Class]] + "]" 。例如:
复制代码 代码如下:
var getClass = Object.prototype.toString;
getClass.call({}); // [object Object]
getClass.call([]); // [object Array]
getClass.call(new Number(1)); // [object Number]
// 等等
这个功能通常是用来检查对象用的,但规范上说宿主对象的[[Class]]可以为任意值,包括内置对象的[[Class]]属性的值,所以理论上来看是不能100%来保证准确的。例如,document.childNodes.item(...)方法的[[Class]]属性,在IE里返回"String",但其它实现里返回的确实"Function"。
复制代码 代码如下:
// in IE - "String", in other - "Function"
alert(getClass.call(document.childNodes.item));
构造函数
因此,正如我们上面提到的,在ECMAScript中的对象是通过所谓的构造函数来创建的。
Constructor is a function that creates and initializes the newly created object.
构造函数是一个函数,用来创建并初始化新创建的对象。
对象创建(内存分配)是由构造函数的内部方法[[Construct]]负责的。该内部方法的行为是定义好的,所有的构造函数都是使用该方法来为新对象分配内存的。
而初始化是通过新建对象上下上调用该函数来管理的,这是由构造函数的内部方法[[Call]]来负责任的。
注意,用户代码只能在初始化阶段访问,虽然在初始化阶段我们可以返回不同的对象(忽略第一阶段创建的tihs对象):
复制代码 代码如下: