JS面向对象(1)——构造函数模式和原型模式

1、构造函数模式

构造函数用来创建特定的类型的对象。如下所示:

function Person(name,age,job){
  this.name=name;
  this.job=job;
  this.age=age;
  this.sayName=function(){
    alert(this.name);
  };
}
var person1=new Person(‘nick‘,20,‘student‘);var person2=new Person(‘nick‘,20,‘student‘);alert(person1.sayName==person2.sayName);//false 

构造函数特点:不需要显示地创建对象,直接将属性和方法赋给this对象;

创建构造构造函数的实例,需要用new操作符,new操作符会创建一个新对象,而后将构造函数的作用域指向新的对象。

构造函数的缺点:上面的例子中,构造函数内的sayName()方法,也可以写为 this.sayName()=new Function("alert(this.name)") 可以看出来,每次创建一个Person的实例都会创建一个新的sayName实例,不同的实例,有不同的作用域链和标识符解析,因此不同实例上的同名函数不相等!

对于这个缺点,我们可以考虑一下:既然在函数内创建的新的sayName实例有不同的作用域链,假设我们将sanName函数定义转义到构造函数外部,那么sayName函数就处于一个全局环境中了!

function Person(name,age,job){
    ...
}
function sayName(){
    alert(this.name);
}
var person2=new Person1(‘alex‘,20,‘student‘);
var person3=new Person1(‘alexx‘,20,‘student‘);
alert(person2.sayName==person3.sayName);//true 两个都是引用同一个全局作用域中定义的函数

2、原型模式

  JS高级程序设计的P147对于原型属性的解释是这样的:每个函数都有一个prototype原型属性,它是一个指针,指向一个对象,这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。怎么理解这句话呢,其实就是我可以创建2个实例person,这两个对象实例继承了构造函数的属性,其中包括prototype,因此它们也就具有了prototype中的所有实例共享的属性和方法了!

  如下,原型模式中,直接把属性方法写到prototype中

function Person(){
}
Person.prototype.name=‘nick‘;
Person.prototype.age=20;
Person.prototype.sayName=function(){
    alert(this.name);
};
var person1=new Person();
var person2=new Person();
person2.name="jack";
alert(person1.name);//nick 继承Person的原型属性,先读取person1实例中的属性,没找到name属性再搜索原型对象中的属性
alert(person2.name);//jack 在实例中添加一个属性,将同名的原型属性屏蔽了
alert(person1.hasOwnproperty(‘name));//true person1实例有name属性
alert(person2.hasOwnproperty(‘name));//true    person2实例没有name属性,它的name属性存在于所继承的Person原型属性中

  (1)通过hasOwnProperty()方法可以检测一个属性是存在实例还是原型中。

  (2)通过in操作符,只要实例或者原型有所查找属性就返回true;

alert("name" in person2);//true name在person的原型中

原型模式的缺陷:

编写原型对象,可以使用对象字面量,但是会导致Person.constructor属性不再指向Person,即

alert(person constructor==Person);//false 

这方面在JS高级程序设计P154中有详细讲到。

还有一个缺陷:前面说到,原型属性是被实例共享的,对于包含基本值的属性来说,如果在某个实例中把某个原型属性修改了就会反映在其他实例中。

function Person(){
}
//用对象字母两来重写整个原型对象更简便
Person.prototype={
    name:‘NICK‘,
    age:20,
    job:‘student‘,
    friend:[‘aa‘,‘bb‘];
    sayName:function(){
        alert(this.name);
    }
}
var person1=new Person();
var person2=new Person();
person1.friend.push(‘cc‘);
alert(person2.friend);//[‘aa‘,‘bb‘,‘cc‘];在person1中修改的内容反映在person2中

组合使用构造函数模式和原型模式

这种方式的好处在于:构造函数可以保持实例属性的独立,原型模式可以定义共享的属性的方法;

 1 function Person(name,age,job){
 2         this.name=name;
 3         this.age=age;
 4         this.job=job;
 5         this.friend=[‘aa‘,‘bb‘];
 6     }
 7
 8     Person.prototype={
 9         constructor:Person,
10         sayName:function(){
11             alert(this.name);
12         }
13     }
14     var person1=new Person(‘nick‘,20,‘student‘);
15     var person2=new Person(‘jerry‘,10,‘student‘);
16
17     person1.friend.push(‘cc‘);
18
19     alert(person1.name);
20     alert(person1.friend);
21     alert(person2.name);
22     alert(person2.friend);//aa bb 往person1的friend添加cc,不会影响到person2因为friend不是原型属性

理解了原型模式,对于后面原型链的认识理解很重要,比如原型链的问题,原型链是通过

function SuperType(){
     this.color=[‘aa‘,‘bb‘];
}
function Subtype(){}
Subtype.prototype=new SuperType();//继承supertype Subtype.prototype成为SuperType的一个实例,因此Subtype建立的实例,都会拥有SubType的原型属性,这个原型属性是共享的!

var instance1=new Subtype();
var instance2=new Subtype();
instance1.color.push(‘cc‘);
alert(instance2.color);//[‘aa‘,‘bb‘,‘cc‘];     

这个缺点同样可以使用构造函数来解决。找时间再写JS面向对象(2)——原型链

第一次写自己学习的一些总结呢,最近在在JS高级程序设计,感觉看了对JS的理解提升很大!加油!

 

时间: 2024-08-09 22:01:10

JS面向对象(1)——构造函数模式和原型模式的相关文章

面向对象JS基础讲解,工厂模式、构造函数模式、原型模式、混合模式、动态原型模式

什么是面向对象?面向对象是一种思想!(废话). 面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法.这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.接下来将为大家讲解在JS中面向对象的实现. 工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,而由于在ECMAScript中无法创建类,因此用函数封装以特定接口创建对象.其实现方法非常简单,也就是在函数内创建一个对象,给对象赋予属性及方法再将对象返回即可. function createBlog(

js设计模式:工厂模式、构造函数模式、原型模式、混合模式

一.js面向对象程序 var o1 = new Object(); o1.name = "宾宾"; o1.sex = "男"; o1.age = "27"; o1.msg = function(){ console.log("姓名:"+this.name+"  性别:"+this.sex+"  年龄:"+this.age); } var o2 = new Object(); o2.nam

js - 创建对象的几种方式(工厂模式、构造函数模式、原型模式)

原文引用https://www.dazhuanlan.com/2019/08/26/5d62f8b594f10/ 工厂模式 做法:内部创建一个对象,并未对象属性赋值并且返回 缺点:解决创建多个相识对象的问题,但不能识别创建的对象的类型 构造函数模式 做法:直接将属性和方法赋值给 this 对象,没有 return 语句 缺点:对象不是共用方法和属性,每 new 一次对象就要创建一个内存,超出性能消耗 原型模式 做法:通过 prototype 为对象添加属性 缺点:每个实例都共享属性方法,实例中修

JS创建对象模式及其对象原型链探究(五):组合使用构造函数模式和原型模式

组合使用构造函数模式和原型模式 构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性. 创建自定义类型的最常见方式,就是组合使用构造函数模式和原型模式. 1.创建对象 // 组合使用构造函数模式和原型模式 function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friend = ["Jenny", "Court"]; } Person.p

Javascript 构造函数模式、原型模式

前两天写完组合继承,打算总结一下原型继承的,不过今天看了一下工厂模式.构造函数模式和原型模式,觉得有必要总结一下以加深印象. ——————————————————————————————————————————————————————————————————————————————————碎碎念. 1.工厂模式 <Javascript 高级程序设计(第3版)> 用了寥寥十多行介绍了工厂模式.我找了一些相关资料,想确定一下这种模式的具体适用场景和优势.按照资料中的说法,是考虑到 ECMAScri

组合使用构造函数模式和原型模式和寄生构造函数

chuangjian自定义类型的最常见方式就是组合使用构造函数模式与原型模式,构造函数模式用于定义实力属性,原型模式定义方法和共享的属性. 寄生构造函数: 原来的写法 var array1 = ['1','2'];var array2 = ['1','2','3'];array1.a = function () { alert(this.length);};array1.a();array2.a = function () { alert(this.length);};array2.a(); 与

浅议javascript的工厂模式,构造函数模式及原型模式

通常来讲我们一般这样创建对象: (1)  var jxj=new Object(); jxj.name="jxj"; jxj.sayHi=function(){console.log("O(∩_∩)O哈哈哈~")}: (2)  var   jxj={name:"jxj",age:"24",.....} 这两种方式在一些场景简单,规模小的项目中使用,我们还可以忍受:但这种方式在可拓展性,可维护性等等方面有很多的问题,于是,就出现

JavaScript创建对象的默认方式:组合使用构造函数模式和原型模式

由于 JavaScript中没有类,对象充当着一系列集合的模板,包含着属性和方法,而每个对象中也有一个原型对象,可以存放共享方法和属性 . 创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式.构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性 //组合使用构造函数模式(构造函数设置自己的属性)和原型模式(原型设计那些共享的方法和属性) function Person(name,age,job){ this.name=name; this.age=age; this.jo

第6章 面向对象的程序设计 6.2 原型模式

我们创建的每个函数都有一个 prototype (原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含特定类型的所有实例共享的属性和方法.按照字面意思来理解,那么 prototype 就是通过调用构造函数而创建的那个对象实例的原型对象.(有点类似于java中的类) 因此不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中,如下所示: function Person(){ } Person.prototype.name = "Nicholas"; P