首页
object类型对象的创建
object类型对象的创建
版权声明:本文为原创内容,转载请声明出处。
原文地址:http://www.excelib.com/article/250/show

ECMAScriptobject类型的对象有三种创建方式:使用初始化器(Initialiser)创建、使用function创建以及使用Object.create方法创建。

使用初始化器(Initialiser)创建

使用初始化器(Initialiser)创建object对象,也就是直接使用花括号来创建,这种方法在很多地方也叫“字面量”或者“对象字面量”,不过在标准中并不属于“字面量”,而是叫“初始化器(Initialiser)”。

使用初始化器创建对象时直接将属性写到花括号中就行了,属性名和属性值使用冒号“:”分开,不同属性之间使用逗号“,”分割(注意,最后一个属性后面没有逗号),属性的值可以是直接量也可以是object类型对象或者function类型对象,我们来看个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
var obj = {
     msg:"obj msg",                    //直接量属性
     innerObj:{                         //object类型对象属性
         msg:"innerObj msg"
     },
     logMsg: function () {                //function类型对象属性
         console.log(this.msg);
     }
 }
  
 console.log(obj.msg);                 //obj msg
 console.log(obj.innerObj.msg);        //innerObj msg
 obj.logMsg();                            //obj msg

这个例子中定义了object类型的对象obj,他包括直接量msgobject类型对象innerObjfunction类型对象logMsg三个属性,其中innerObj对象也是通过初始化器(花括号)来定义的。定义完对象之后又分别使用obj对象调用了他的三个属性。

object对象调用属性有两种方法:1、直接使用点操作符调用;2、使用方括号来调用。因为使用方括号没有使用点操作符方便,所以使用点操作符来调用的比较多,不过当属性名为一个变量时则需要使用方括号来调用,比如下面的例子

1
2
3
var obj = {a:1,b:2,c:3};
 var propName = "c";
 console.log(obj[propName]);     //3

这里的属性名保存在propName变量中,这时就需要使用方括号来调用了。

使用function创建

使用function创建object实例对象我们在前面function中已经讲过了,是使用new关键字来创建的,而且创建出来的对象还可以使用functionprototype属性对象中的属性,具体的内容我们这里就不再重述了。

使用Object.create方法创建

还有一种创建object类型对象的方式,那就是使用Object.create来创建。ObjectECMAScript中内置的一个function类型的对象,createObject对象的一个属性方法,其作用是根据传入的参数创建object类型的对象,create方法的调用语法为

Object.create(prototype, [ propertiesObject ])

这里的第一个参数prototype是创建出的对象所对应的prototype,也就是相当于使用function创建时function中的prototype属性对象,创建出来的object对象实例可以直接调用。

第二个参数propertiesObject为属性描述对象,是可选参数,属性描述对象是object对象类型,它里面的属性名会成为创建出来对象的属性名,属性值为属性的描述对象,其中包含属性的特性,属性的特性我们后面会详细讲解,这里大家只要知道其中的value就是属性值就可以了,我们来看个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var obj = Object.create(
        // prototype
          {
              type: "by create"
          },
        // propertiesObject
          {
              color: {
                  value: "red",
                  enumerable: true
              },
              size: {
                  value: "37",
                  enumerable: true
              }
          }
  );
  
 console.log(obj.type);                       // by create
 console.log(obj.color);                      // red            
 console.log(obj.size);                       // 37
 console.log(Object.getOwnPropertyNames(obj));      //  ["color", "size"]

这里使用Object.create创建了一个obj对象,第一个参数prototype中有一个属性type,第二个参数propertiesObject有两个属性:colorsize,创建出来的obj对象这三个属性都可以使用,不过自己其实只有两个属性,prototype中的type属性虽然obj可以调用,但是并不属于obj所有,使用Object.getOwnPropertyNames方法就可以获取到obj自己所拥有的属性。

另外,需要注意的一点是使用初始化器(花括号)和function创建出来的对象都可以调用Objectprototype属性对象中的属性,也就是说那两种方法创建出来的对象首先会拥有公共的prototype,然后如果是使用function创建的对象还可以调用functionprototype中的属性,而且即使functionprototypenull,创建出来的对象也可以调用Objectprototype中的属性,但是使用Object.create创建对象时如果第一个参数为null,那么他创建出来的对象就不可以调用Objectprototype中的属性了,我们看下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 使用初始化器创建对象braceObj
 var braceObj = {}
  
 // 使用function创建对象functionObj
 function F(){}
 F.prototype = null;
 var functionObj = new F();
  
 // 使用create方法创建对象createObj
 var createObj = Object.create(null);
  
 console.log(braceObj.toString());        //[object Object]
 console.log(functionObj.toString());     //[object Object]
 console.log(createObj.toString());       //抛出方法没找到异常


这里的toString方法是Objectprototype属性中的一个方法,如果创建出来的对象可以调用toString方法就说明可以调用Objectprototype属性对象中的方法,否则就是不可以调用。从这个例子中可以看出使用花括号和function创建的对象都可以调用,而且即使将functionprototype设置为null,创建出来的对象也可以调用,但使用Object.create创建出来的对象如果其prototype参数为null就不可以调用了。


多知道点

Objectprototype属性对象里面都有什么

Objectprototype属性对象在ECMAScript5.1ECMAScript2015中都规定有constructortoString ( )toLocaleString ( )valueOf ( )hasOwnProperty (V) isPrototypeOf (V)propertyIsEnumerable (V)七个属性,其中constructor会默认指向创建对象的function,其他六个是方法,我们分别来看一下。

  • toString:这是六个方法中最常使用的方法,他可以将对象转换为字符串,不同类型的对象可能会重新自己的toString方法,比如Array的toString方法会将其所包含的元素使用逗号连接起来组成字符串并返回、Date的toString方法会返回Date的时间字符串,普通object类型对象会返回[object Object];

  • toLocaleString:toLocaleString方法会使用本地化格式来生成字符串,特别是时间日期类型和数字类型;

  • valueOf:会返回原始值,比如Date类型对象是通过数字来保存的,所以当Date类型对象调用valueOf时就会获得相应的数字;

  • hasOwnProperty:判断是否包含指定属性,注意,这里判断的是对象本身是否包含指定的属性,不包括创建对象的function对象的prototype属性中的对象;

  • isPrototypeOf:判断是不是另一个对象所对应的prototype对象;

  • propertyIsEnumerable:判断某个属性是否可以枚举,关于属性的枚举我们到属性的特性一节再详细介绍。


下面我们来看例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function log(msg){
      console.log(msg);
  }
  
 var array = [1,3,5];
 var date = new Date();
 log(array.toString());       // 1,3,5
 log(date.toString());        // Tue Jun 09 2015 10:48:10 GMT+0800
 log(date.toLocaleString());  // 2015/6/9 上午10:48:10
 log(date.valueOf());         // 1433818090599  从1970年到现在的毫秒数
  
 var Obj = function(){
     this.msg = "hello";
     this.say = function () {
         log(msg);
     }
 }
 var proto = {color: "red"};
 Obj.prototype = proto;
 var obj = new Obj();
  
 log(obj.constructor);                       // Object()
 log(obj.hasOwnProperty("msg"));          // true
 log(obj.hasOwnProperty("color"));         // false,color在Obj的prototype中,obj虽然可以调用但是不拥有
 log(obj.propertyIsEnumerable("msg"));     // true
 log(obj.isPrototypeOf(proto));              // false
 log(proto.isPrototypeOf(obj));              // true

从这个例子中我们就可以理解Objectprototype属性对象中的七个属性的用法了,需要注意的是因为我们给Objprototype属性赋值为了proto对象,所以创建出来的obj对象调用constructor属性就不会返回我们的Obj对象而是返回Object对象了,我们可以通过对proto对象进行修改来修复这一问题,修复代码如下

1
2
3
4
5
6
var proto = {color: "red"};
  
proto.constructor = Obj;
 Obj.prototype = proto;
 var obj = new Obj();
 console.log(obj.constructor);                    // Obj

这时就可以正确地输出constructor了。

上面是标准中规定的Objectprototype属性对象中的七个属性,但是不同的浏览器还会有一些自己的扩展,比如在FireFox中就扩展到了14个属性:constructortoSourcetoStringtoLocaleStringvalueOfwatchunwatchhasOwnPropertyisPrototypeOfpropertyIsEnumerable__defineGetter____defineSetter____lookupGetter____lookupSetter__,不过新增的属性并不是通用属性,在别的浏览器中可能并没有定义,如果使用的话就可能会造成浏览器不兼容的问题,我们应该尽量少使用,如果非要用就要在使用前先判断浏览器是否支持。