构造函数
Posted lailailee
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了构造函数相关的知识,希望对你有一定的参考价值。
构造函数就是初始化一个实例对象,对象的prototype属性是继承一个实例对象
下面两个例子:
1 function creatPerson(name,age,job){ 2 //工厂模式创建对象 3 var o=new Object(); 4 o.name=name; 5 o.age=age; 6 o.job=job; 7 o.sayName=function(){ 8 alert(this.name); 9 }; 10 return o; 11 } 12 var person1=creatPerson(‘LiMing‘,29,‘Doctor‘); 13 var person1=creatPerson(‘Greg‘,17,‘Teacher‘);
1 function Person(name,age,job){ 2 //构造函数模式创建对象 3 var o=new Object(); 4 this.name=name; 5 this.age=age; 6 this.job=job; 7 this.sayName=function(){ 8 alert(this.name); 9 }; 10 } 11 var person1=Person(‘LiMing‘,29,‘Doctor‘); 12 var person1=Person(‘Greg‘,17,‘Teacher‘);
Person()中的代码除了与creatPerson()中相同的部分外,还存在以下不同之处:
1.没有显式地创建对象;
2.直接将属性和方法赋给了this对象;
3.没有return语句;
4.函数名以大写字母开头。
要创建Person新实例,,必须使用new操作符。
使用new调用构造函数实际会经历以下四个步骤:
1.创建一个新对象;
2.将构造函数的作用域赋给新对象(this指向这个对象);
3.执行构造函数中的代码(为这个新对象添加属性);
4.返回新对象(返回this)。
Person()中的两个实例person1和person 2都有一个constructor(构造函数)属性,该属性指向Person:
alert(person1.constructor==Person); //true alert(person2.constructor==Person); //true
对象的constructor属性最初是用来表示对象类型的,但要检测对象类型,还是用instanceof操作符。
我们在这个例子中创建的所有对象既是Object的实例,同时也是Person的实例:
alert(person1 instanceof Object); //true alert(person1 instanceof Person); //true alert(person2 instanceof Object); //true alert(person2 instanceof Person); //true
1.将构造函数当做函数
构造函数与其他函数的唯一区别,就在于他们的调用方式不同。
不过,构造函数毕竟也是函数,不存在定义构造函数的特殊语法。
任何函数,只要通过new操作符来调用,那它就可以作为构造函数;而任何函数,如果不通过new操作符调用,那它跟普通函数也没什么两样。
//当作构造函数使用 var person=new Person(‘LiMing‘,29,‘Doctor‘); person.sayName(); //LiMing //作为普通函数使用 Person(‘LiMing‘,29,‘Doctor‘); //添加到window window.sayName(); //在全局作用域 中调用一个函数时,this对象总是指向Global对象(在浏览器中就是全局对象) //在另一个对象的作用域中调用 var o=new Object(); //可以使用call()(或者apply())在某个特殊对象的作用域中调用Person()函数 Person.call(o,‘LiMing‘,29,‘Doctor‘); o.sayName();
2.构造函数的问题
构造函数模式虽然方便好用,但使用构造函数还有一个主要问题,就是每个方法都要在每个实例上重新创建一遍。
在前面的例子中,person1和person2都有一个名为sayName()的方法,但那两个方法不是同一个Function的实例。
此时的构造函数相当于:
1 function Person(name,age,job){ 2 //构造函数模式创建对象 3 var o=new Object(); 4 this.name=name; 5 this.age=age; 6 this.job=job; 7 this.sayName=new Function(alert(this.name)); 10 }
alert(person1.sayName == person2.sayName); //false
然而,创建两个完成同样任务的Function实例的确没有必要;况且有this对象在,根本不用在执行代码前就把函数绑定到特定对象上面。因此,可以通过把函数定义转移到构造函数外部来解决这个问题。
1 function Person(name,age,job){ 2 //构造函数模式创建对象 3 var o=new Object(); 4 this.name=name; 5 this.age=age; 6 this.job=job; 7 this.sayName=sayName; 8 } 9 10 function sayName(){ 11 alert(this.name); 12 } 13 14 var person1=Person(‘LiMing‘,29,‘Doctor‘); 15 var person2=Person(‘Greg‘,17,‘Teacher‘);
这样,sayName()函数就成为了全局函数,Person()函数中的sayName就是一个指向函数sayName()的指针,person1,person2对象就共享了在全局作用域中定义的同一个sayName()函数。
那么新问题又来了:如果对象需要定义很多方法,那么就要定义很多全局函数,于是这个自定义的引用类型就毫无封装性可言了。
这个问题可以通过原型模式来解决......
以上是关于构造函数的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段