一、通过闭包,执行匿名函数,返回一个对象
//例1 var Test = function(){ var a = 1; //在这里定义的变量,比如a、b、c、d,在整个Test下都可以访问到 var b = 10; var c; function hhh(){ a = 2; b = 20; //对于a、b、c等变量的处理... } return{ a:a,//只能获取a刚定义时的值1,而不能获取程序在运行中实时a的值,不要使用这种写法 getB:function(){ return b;//可以获取程序在运行中b实时的值20;(正确的写法) } } }();//()是执行函数的运算符(此处是执行一个匿名函数,然后返回一个对象) Test是一个对象,可以为对象添加属性:Test.d = 30; 此时,在外界就可以通过Test.d获取值。 //例2 var person = function(){ var name = "default";//变量作用域为函数内部,外部无法访问 return { getName : function(){ return name; }, setName : function(newName){ name = newName; } } }(); alert(person.name); //直接访问,结果为undefined alert(person.getName()); //default person.setName("gerry"); alert(person.getName()); //gerry
二、直接调用函数,返回一个对象
//例1 function Point(left, top){ this.left = left;//注意:此处的this是指向window对象的,this===window为true!先把值存储在window对象的一个属性中,再取出来 this.top = top; //handle the left and top... return {x: this.left, y:this.top}; } 直接动态的构建一个新的匿名对象返回即可: var pos = Point(3, 4); //pos.x = 3; pos.y = 4; //例2 function Person(){ var name = "default"; return { getName : function(){ return name; }, setName : function(newName){ name = newName; } } }; var john = Person(); alert(john.getName()); //打印default john.setName("john"); alert(john.getName()); //打印john alert(john.constructor) //john只是普通的对象,输出function Object(){[native code]} var jack = Person(); alert(jack.getName()); //打印default jack.setName("jack"); alert(jack.getName()); //打印jack 由此代码可知,john和jack都可以称为是Person这个类的实例,因为这两个实例对name这个成员的访问是独立的,互不影响
三、定义对象的“类”:原型,然后使用new操作符来批量的构筑新的对象
//定义一个"类",Address function Address(street, xno){ this.street = street || 'Shanghai Road'; this.xno = xno || 135; this.toString = function(){ return "street : " + this.street + ", No : " + this.xno; } } //定义另一个"类",Person function Person (name, age, addr) { this.name = name || 'unknown'; this.age = age; this.addr = addr || new Address(null, null); this.getName = function(){return this.name;} this.getAge = function(){return this.age;} this.getAddr = function(){return this.addr.toString();} } //通过new操作符来创建两个对象,注意,这两个对象是相互独立的 var jack = new Person('jack', 26, new Address('Qing Hai Road', 123)); var gerry = new Person('gerry', 25); //查看结果 alert(jack.getName()); //打印jack alert(jack.getAge()); //打印26 alert(jack.getAddr()); //打印street : Qing Hai Road, No : 123 alert(gerry.getName()); //打印gerry alert(gerry.getAge()); //打印25 alert(gerry.getAddr()); //打印street : Shanghai Road, No : 135
对new操作符进行讲解
我们来看一个例子: function Shape(type){ this .type = type || "rect" ; this .calc = function (){ return "calc, " + this .type; } } var triangle = new Shape("triangle"); alert(triangle.calc()); //打印 calc, triangle alert(triangle.constructor==Shape);//true alert(triangle.prototype); //undefined var circle = new Shape("circle"); alert(circle.calc()); //打印 calc, circle 在javascript中,通过new操作符来作用与一个函数,实质上会发生这样的动作: 首先,创建一个空对象,然后用函数的apply方法,将这个空对象传入作为apply的第一个参数,及上下文参数。这样函数内部的this将会被这个空的对象所替代: var triangle = new Shape("triangle"); //上一句做了以下两行代码的工作: var triangle = {}; Shape.apply(triangle, ["triangle"]); 当我们使用new操作符时,javascript会: 1、生成一个空对象{} 2、执行构造函数(实际上就是普通函数),将函数中的this用刚生成的空对象代替,相当于给刚生成的空对象添加属性及值,完成成员设置等初始化工作。即:生成的对象被new后面的方法(函数)的this关键字引用!然后在方法中通过操作this,就给这个新创建的对象相应的赋予了属性.然后返回这个经过处理的对象. 3、初始化对象(实际上现在已经有了属性,是构造函数赋予的)的constructor属性,让他的值为构造函数(函数也是对象)。所以创建对象的时候没有初始化prototype,而是初始化了constructor,指向构造函数。 这样上面的例子就很清楚:先创建一个空对象,然后调用Shape方法对其进行赋值,返回该对象,最后再初始化对象的constructor属性,这样我们就得到了一个triangle对象. 对象建立之后,对象上的任何访问和操作都只与对象自身及其原型链上的那串对象有关,与构造函数再扯不上关系了。换句话说,构造函数只是在创建对象时起到介绍原型对象和初始化对象两个作用。 例如: var p = new Person(); 此时,p会含有一个constructor属性,指向它的构造函数Person p.constructor==Person p.constructor.prototype.age //p.constructor.prototype即是 构造函数的prototype属性对应的prototype对象
参考:http://abruzzi.iteye.com/博客中的“javascript内核系列”