Javascript中的对象并不像传统编程语言中的对象一样,ECMAScript规范把对象定义为:无序属性的集合,其属性可以包含基本值、对象或函数
也就是说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。所以可以把Javascript对象想象成散列表即一组名值对,其值可以使数据或函数。每个对象都是基于一种引用类型创建的,可以使内置类型也可以使自定义类型
【创建对象】
1 //创建一个对象,它拥有三个属性和一个方法 2 var person=new Object(); 3 person.name="Jack"; 4 person.age=27; 5 person.job="Software Engineer"; 6 person.sayName=function(){ 7 document.write(this.name); 8 }; 9 //用对象字面量法创建对象10 var person={11 name:"Jack",12 age:27,13 job:"Software Engineer",14 sayName:function(){15 document.write(this.name);16 }17 };
【属性的类型】
在ECMAScript中有两种属性:数据属性和访问器属性。
数据属性
数据属性是包含一个数据值的位置,在这个位置可以读取和写入值,数据属性有4个描述其行为的特征
属性的特征 | ||
属性 | 值 _表示默认值 | 说明 |
[[Configurable]] | true,false | 能否通过delete删除属性从而重新定义属性 能否修改属性的特性 能否把属性修改为访问器属性 |
[[Enumerable]] | true,false | 能否通过for-in循环返回属性 |
[[Writable]] | true,false | 能否修改属性的值 |
[[Value]] | undefined,false | 包含这个属性的数据值 |
在上面创建person对象,它的属性特征[[Configurable]]、[[Enumerable]]、[[Writable]]的值都为true,[[Value]]即为属性的数据值
修改默认的属性的特征:
使用ECMAScript 5的defineProperty()方法可以修改属性的默认特性。如下
1 //修改属性的默认特性2 var person={}; //字面量表示法创建空对象3 Object.defineProperty(person,"name",{4 writable:false,5 value:"Jack"6 });7 document.write(person.name);8 person.name="Tom"; //修改属性的值9 document.write(person.name);
defineProperty()方法接受三个参数:属性所在的对象,属性名称和一个描述对象。上面代码修改了name属性的默认特性,使得writable:false即不能修改属性的值。所以,当打算把person.name="Tom"; 时在非严格模式下赋值操作被忽略,在严格操作模式下,会发生错误
【 常用的设计模式】
工厂模式
工厂模式抽象了创建具体对象的过程,由于在Javascript中没有类,所以依靠的是函数来模拟,即用函数来封装以特定接口创建对象的细节
1 //用工厂模式创建对象 2 function createPerson(name,age,address){ 3 var o=new Object(); 4 o.name=name; 5 o.age=age; 6 o.address=address; 7 o.sayName=function(){ 8 alert(this.name); 9 };10 return o;11 12 }13 var person1=createPerson("Jack",29,"NanJing");14 var person2=createPerson("Tom",25,"Suzhou");
可以无数次的调用这个函数,它每次都会返回一个对象,这个对象有三个属性和一个方法。
构造函数模式
Javascript中内置的构造函数原本是用来创建特别类型的对象,这些利用构造函数创建的对象,都具有默认的属性和方法, 但也可以自定义构造函数,从而自定义对象的属性和方法
1 function Person(name,age,address){ 2 this.name=name; 3 this.age=age; 4 this.address=address; 5 this.sayName=function(){ 6 alert(this.name); 7 }; 8 } 9 var person1=new Person("Jack",29,"NanJing");10 var person2=new Person("Tom",25,"Suzhou");
根据惯例非构造函数首字母一般小写,构造函数的首字母应该大写,以示区别构造函数本身也是函数,只不过是用来创建对象罢了。调用构造函数创建对象会经历四个过程
一.创建一个新对象
二.将构造函数的作用域赋给新对象
三.执行构造函数中的代码
四.返回新对象
需要注意的是自定义的类型最终也是Object对象的实例,因为所有对象均继承自Object对象
构造函数也可以当做普通函数使用
构造函数与普通函数的区别就在调用方式上不一样,定义构造函数与普通函数的定义方法是一致的。对于任何函数使用new操作符调用即被当做构造函数使用,不使用new操作调用即是普通函数。下面是构造函数的几种调用方式
1 //定义函数 2 function Person(name, age, address) { 3 this.name = name; 4 this.age = age; 5 this.address = address; 6 this.sayName = function () { 7 alert(this.name); 8 }; 9 }10 //当构造函数来调用11 var person1 = new Person("Jack", 29, "NanJing");12 var person2 = new Person("Tom", 25, "Suzhou");13 alert(person1.sayName());14 //作为普通函数调用15 Person("Lucy", 21, "BeiJing"); //添加到window16 window.sayName();17 //在另一个对象的作用域中调用18 var p = new Object();19 Person.call(o, "Justin", 22, "ShangHai");20 o.sayName();
原型模式
在Javascript中每个函数都有一个prototype属性(函数是有属性的,因为函数式对象),这个属性是一个指针,指向一个对象,这个对象的作用:包含特定类型所有实例的方法和属性。也就是说无论何时只要创建一个新函数,引擎就会根据一定的规则创建一个原型属性prototype,这个原型属性指向原型对象,默认情况下所有原型对象都会自动获得一个constructor构造函数属性