作者:zccst
思路:工厂模式-->构造函数-->原型模式
一、工厂方法
存在问题:没有解决对象识别问题,即怎样知道一个对象的类型。
二、构造函数方式
构造函数可用来创建特定类型的对象。像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中。此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。
构造函数的特点(与工厂方法的不同之处有)
(1)没有显示地创建对象
(2)直接将属性和方法赋给了this对象
(3)没有return 语句。
(4)首字母大写Person
使用new调用构造函数,实际会经历四个步骤:
(1)创建一个新对象
(2)将构造函数的作用域赋给新对象(this指向了这个新对象)
(3)执行构造函数中的代码(为这个新对象添加属性)
(4)返回新对象
前面p1和p2分别保存着Person的一个不同的实例。这两个对象都有一个constructor属性,该属性指向Person
alert(p1.constructor);//把Person对象打印一遍。
alert(p1.constructor == Person);//true
对象的constructor属性最初是用来表示对象类型的,但是instanceof操作符更可靠。
alert(p1 instanceof Person);//true
alert(p1 instanceof Object);//true
优点:创造自定义的构造函数意味着将来可以将他的实例标识为一种特定的类型;而这正是构造函数胜过工厂模式的地方。
存在问题:构造函数的问题是创建多少次,解决有多少个副本。不同对象间完全没有关系。缺点是:不能复用。
备注,这种方式定义的构造函数是定义在Global对象的。
1,将构造函数当成函数
构造函数与其他函数的唯一区别,就在于调用他们的方式不同。不过构造函数毕竟也是函数,不存在定义构造函数的特殊语法。 任何函数,只要通过new操作符来调用,那他就可以作为构造函数;而任何函数,如果不通过new操作符来调用,那它跟普通函数也不会有什么两样。 例如,前面例子定义的Person()函数可以通过下列任何一种方式来调用
最上面是构造函数的典型用法
2,构造函数的问题
主要问题是,每个方法都要在每一个实例上重新创建一遍。
从这个角度来看构造函数,更容易明白每个Person实例都包含一个不同的Function实例的本质。如下代码可以证明这两个函数是不相等的。
alert(p1.sayName == p2.sayName); // false;
然而,创建两个完全同样任务的Function实例确实没有必要,况且还有this对象在,根本不用在执行代码前就把函数绑定到的特定对象上。因此,大可像下面这样,
主要问题是,每个方法都要在每一个实例上重新创建一遍。
把sayName()函数的定义转移到了构造函数外,构造函数内的this.sayName 设置为全局作用域的 sayName;,尽管解决了两个函数做同一件事的问题。
可新问题又来了,在全局作用域中定义的函数实际上只被某个对象调用,这让全局作用域有点名不副实。而更让人无法接受的是:如果对象需要定义很多方法,那么就要定义很多个全局函数,于是我们这个自定义的引用来写就丝毫没有封装性可言了。好在这些问题都可以通过使用原型模式来解决。
思路:工厂模式-->构造函数-->原型模式
一、工厂方法
- createPerson(name ,sex, age){
- var o = new object();
- o.name = name;
- o.sex = sex;
- o.age = age;
- o.sayName = function(){
- return this.name;
- }
- return o;
- }
存在问题:没有解决对象识别问题,即怎样知道一个对象的类型。
二、构造函数方式
构造函数可用来创建特定类型的对象。像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中。此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。
- function Person(name,age,job)
- {
- this.name = name;
- this.age = age;
- this.job = job;
- this.sayName = function(){
- alert(this.name);
- }
- //本质是 new function(){};每一个对象都不能共用
- }
- var p1 = new Person('Nicholas', 27, 'soft');
- var p2 = new Person('zhao' , 26, 'ps');
- p1.sayName();
- p2.sayName();
构造函数的特点(与工厂方法的不同之处有)
(1)没有显示地创建对象
(2)直接将属性和方法赋给了this对象
(3)没有return 语句。
(4)首字母大写Person
使用new调用构造函数,实际会经历四个步骤:
(1)创建一个新对象
(2)将构造函数的作用域赋给新对象(this指向了这个新对象)
(3)执行构造函数中的代码(为这个新对象添加属性)
(4)返回新对象
前面p1和p2分别保存着Person的一个不同的实例。这两个对象都有一个constructor属性,该属性指向Person
alert(p1.constructor);//把Person对象打印一遍。
alert(p1.constructor == Person);//true
对象的constructor属性最初是用来表示对象类型的,但是instanceof操作符更可靠。
alert(p1 instanceof Person);//true
alert(p1 instanceof Object);//true
优点:创造自定义的构造函数意味着将来可以将他的实例标识为一种特定的类型;而这正是构造函数胜过工厂模式的地方。
存在问题:构造函数的问题是创建多少次,解决有多少个副本。不同对象间完全没有关系。缺点是:不能复用。
备注,这种方式定义的构造函数是定义在Global对象的。
1,将构造函数当成函数
构造函数与其他函数的唯一区别,就在于调用他们的方式不同。不过构造函数毕竟也是函数,不存在定义构造函数的特殊语法。 任何函数,只要通过new操作符来调用,那他就可以作为构造函数;而任何函数,如果不通过new操作符来调用,那它跟普通函数也不会有什么两样。 例如,前面例子定义的Person()函数可以通过下列任何一种方式来调用
- //当构造函数使用
- var person = new Person("Nicholas",29,"Software Engineer")
- person.sayName(); //Nicholas
- //作为普通函数使用
- Person("Nicholas",29,"Software Engineer")
- window.sayName(); //Nicholas
- //在另一个对象作用域调用
- var o = new Object();
- Person.call(o, "Kristen", 25, "Nurse");
- o.sayName(); //Kristen
最上面是构造函数的典型用法
2,构造函数的问题
主要问题是,每个方法都要在每一个实例上重新创建一遍。
- function Person(name,age,job)
- {
- this.name = name;
- this.age = age;
- this.job = job;
- this.sayName = new Function(){//与声明函数在逻辑上是等价的
- alert(this.name);
- }
- }
从这个角度来看构造函数,更容易明白每个Person实例都包含一个不同的Function实例的本质。如下代码可以证明这两个函数是不相等的。
alert(p1.sayName == p2.sayName); // false;
然而,创建两个完全同样任务的Function实例确实没有必要,况且还有this对象在,根本不用在执行代码前就把函数绑定到的特定对象上。因此,大可像下面这样,
主要问题是,每个方法都要在每一个实例上重新创建一遍。
- function Person(name,age,job)
- {
- this.name = name;
- this.age = age;
- this.job = job;
- this.sayName = sayName;
- }
- function sayName(){
- alert(this.name);
- }
- var p1 = new Person('Nicholas', 27, 'soft');
- var p2 = new Person('Greg' , 26, 'ps');
- alert(p1.constructor == Person);//true
- alert(p2.constructor == Person);//true
- alert(p1.sayName == p2.sayName); //true;
把sayName()函数的定义转移到了构造函数外,构造函数内的this.sayName 设置为全局作用域的 sayName;,尽管解决了两个函数做同一件事的问题。
可新问题又来了,在全局作用域中定义的函数实际上只被某个对象调用,这让全局作用域有点名不副实。而更让人无法接受的是:如果对象需要定义很多方法,那么就要定义很多个全局函数,于是我们这个自定义的引用来写就丝毫没有封装性可言了。好在这些问题都可以通过使用原型模式来解决。