JavaScript高级 面向对象的程序设计 (一)

  • 创建对象
  • 继承

面向对象的语言都有一个表示---类。通过类我们可以创建多个具有相同属性的对象。但是,在JS中并没有类的概念,所以JS的对象也和其他语言的对象不同。

对象的定义:无序的属性集合,其属性可以包含基本值,对象,函数。(所以我们又可以把JS对象看成散列表,一组键值对。)

一、创建对象

1.1工厂模式

function createPerson(name,age){

var o =newObject();

o.name = name;

o.age= age;

o.sayName =function(){

alert(this.name);

}

  return o;

}

 

var person1 =createPerson(‘zzz‘,15);

var person2 =createPerson(‘jjj‘,14);

此种方式无法判断它的类型,只能知道是Object类型。

1.2构造函数模式

functionPerson(name,age){

this.name = name;

this.age = age;

this.sayName =function(){

alter(this.name);

};

}

var per =newPerson();

此种方式解决了可以判断它为Person类型同时也是Object类型。

但是,这个方式每次创建一个新的对象都会 讲对象的中的方法重新创建一遍。

1.3原型模式

每个函数都有个属性--prototype。prototype是一个指针,指向一个对象,这个对象的用途是 包含 特定类型的所有实例  共享 的属性和方法。

functionPerson(){};

Person.prototype.name =‘zjh‘;

Person.prototype.age =15;

Person.prototype.getName =function(){

alert(this.name);

};

var per =newPerson();

alert(per.__proto__ ==Person.prototype)//true

1.3.1理解原型对象

只要创建了一个函数,那么就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向该函数的原型对象。在默认情况下,所有的原型对象都会获得一个constructor(构造函数)属性,这个属性是一个指针,指向拥有该prototype的函数。所以Person.prototype.constructor = Person  ,这是一个循环。

当构造函数创建了一个实例,那么这个实例自动就会含有一个属性(__proto__),这个属性指向创建这个对象的构造函数的原型对象。(  per.__proto__ == Person.prototype

也就是实例和构造函数没有直接关系。虽然在创建的person1中没有任何属性和方法,但是根据原型链规则,他会自动查找它的原型链上的所有属性。

1.3.2原型与in操作符

functionPerson(){};

Person.prototype.name =‘zjh‘;

Person.prototype.age =15;

Person.prototype.getName =function(){

alert(this.name);

};

var per =newPerson();

per.daddy =‘zyj‘

for(var a in per){

alert(a)

}

1.3.3简洁的原型语法

functionPerson(){};

Person.prototype ={

name :‘zjh‘,

age :15,

getName :function(){

alert(this.name);

}

}

这种方式存在一个问题:当Person.prototype指向一个字面量时,这个字面量会生成一个对象,那么Person.prototype.constructor就是这个新生成对象的constructor,而这个对象的constructor一般都是Object.

解决这个问题可以通过下面这个技巧:

functionPerson(){};

Person.prototype ={

constructor :Person,

name :‘zjh‘,

age :15,

getName :function(){

alert(this.name);

}

}

var p =newPerson();

alert(p.constructor);

但是这种方式会使constructor属性变成可遍历的

这种方式可以使其隐藏。

1.3.4原型的动态性

因为对象查找值是在原型链上查找的,所以一旦在对象的原型上添加或删除属性或者方法,就会在对象上生效,即使是以前的对象。

但是如果构造函数的原型被重新创建(比如说像上面直接用字面量方式写原型),那么实例的原型仍然指向最初的内存位置,而此时该位置已经不存在了。

1.3.5原生对象的原型

可以对原生的构造函数原型修改,但一般不推荐这样做。

1.3.6原型对象的问题

其一就是无法在构造对象时就添加初始化参数,而必须预先定义值。

其二是一些由共享性导致的问题:

functionPerson(){};

Person.prototype ={

constructor :Person,

name :‘zjh‘,

age :15,

pie :[‘a‘,‘b‘],

getName :function(){

alert(this.name);

}

}

var p =newPerson();

p.pie.push(‘c‘);

alert(p.hasOwnProperty("pie"))//false

alert(p.pie)//a,b,c

var pp =newPerson();

alert(pp.pie)//a,b,c

所以通常都不会单独使用原型模式。

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

创建自定义类型最常见的方式就是组合使用构造函数模式和原型模式。构造函数模式用于定义实例属性,原型模式用于定义方法和共性的属性。这样就让每个实例都有一份自己的属性副本,但同时又共享方法的引用,极大的节省了内存。同时还支持向构造函数内传参。

这是写法也是一种认同度最高的创建方式。

1.3.8动态原型模式

functionPerson(name,age){

this.name = name;

this.age = age;

if(typeof(this.getName)!=‘function‘){

alert(‘s‘)

Person.prototype.getName =function(){

alert(this.name);

}

}

};

var p1 =newPerson(1,2);

var p2 =newPerson(1,2);

只会在创建p1的时候弹出s,之后就不会再执行if内语句了。

1.3.9寄生构造函数模式

一般在前几种方式都不适用的情况下,使用寄生构造函数模式。

在特殊情况下我们要使用这种方式:

这种方法的局限性在于创建的对象和构造函数在原型上没有关系,也不能更具instanceOf来确定类型。所以,在可以用以上类型的情况下,不要使用这种情况。

1.3.10稳妥构造函数模式

所为稳妥对象,指的是没有公共属性,而且其方法也不用引用this对象。稳妥对象最适合在一些安全的环境中(这些环境会禁止使用this、new),或者在防止数据被其他应用程序改动时使用。

它与上面的寄生构造函数模式类似。两点不同:一是新创建对象的实例方法不引用this,二是不使用new操作符调用构造函数。

functionPerson(name,age){

var o =newObject();

var name =‘zjh‘;

o.getName =function(){

alert(name);

}

return o;

};

var p1 =Person(1,2);

p1.getName();

同样和寄生构造函数模式一样,这样创造出的对象和构造函数之间没有关系。

时间: 2024-08-16 06:39:35

JavaScript高级 面向对象的程序设计 (一)的相关文章

JavaScript高级 面向对象的程序设计 (二)

二.继承 OO是面向对象语言最为有魅力的概念.一般的OO语言都实现了两种继承,接口继承和实现继承.接口继承只继承方法签名,而实际继承继承了实际的方法. 而在JS中,函数没有签名,所以无法实现接口继承.只能依靠原型链--实现继承. 2.1原型链 JS中描述了原型链的概念,并利用原型链作为实现继承的主要方法. 其基本思想:利用原型链让一个引用类型继承另一个引用类型的属性和方法. functionSuperF(){ this.superPropty ='B'; } SuperF.prototype.g

JavaScript基础——面向对象的程序设计(一)创建对象的几种方式总结

简介 面向对象(Object-Oriented, OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.前面提到过,ECMAScript中没有类的概念,因此它的对象也与基于类的语言中的对象有所不同. ECMA-262把对象定义为:"无序属性的集合,其属性可以包含基本值.对象或者函数."严格来讲,这就相当于说对象是一组没有特定顺序的值.对象的每个属性或方法都有一个名字,而每个名字都映射到一个值.正因为这样(以及其他将要讨论的原因),我们可以把E

JavaScript高级 面向对象(1)--添加一个div标签

说明(2017.3.28): 1. JavaScript是一种基于对象的多范式编程语言,不是面向对象,但离开对象不能活. 范式编程是指编程习惯.方式,分为过程式.对象式和函数式编程. 2. 面向对象是指,使用对象进行开发,面向对象是对面向过程的封装. 3. JavaScript面向对象的三个特点,抽象性.继承性和封装性. 抽象性是指,抽取出核心属性和方法,不在特定条件下不能确定对象的具体意义. 继承性是指,把我没有的属性和方法拿来使用,并变成自己的属性和方法. 封装性是指,把方法和属性打包成一个

JavaScript高级 面向对象(13)--构造函数的执行过程

说明(2017-4-2 21:50:45) 一.构造函数是干什么用的: 1. 初始化数据的. 2. 在js给对象添加属性用的,初始化属性值用. 二.创建对象的过程: 1. 代码:var p = new Person(); 2. 首先运算符new创建了一个对象,它类似于{},是一个"没有任何成员"的对象. * 使用new创建对象,对象的类型就是创建它的构造函数名(如,Person类型). * 使用{}无论如何都是Object类型,相当于"new Object()".

JavaScript高级 面向对象(12)--引用类型值类型作为参数传递的特性

说明(2017-4-2 18:27:11): 1. 作为函数的参数,就是将函数的数据拷贝一份,传递给函数的定义中的参数. 函数foo()在调用的时候,做了两件事: (1)函数在调用的时候,首先需要将参数中的数据拷贝一份,即数字123拷贝一份. (2)跳转到函数的定义中(函数体),在此之前完成了函数的赋值,即num=123. (3)正式的进入函数内,准备执行函数的每一句话. 1 function foo(num){} 2 var a = 123; 3 foo(a); 2. 值类型作为函数参数传递的

JavaScript高级 面向对象(10)--onload与jq中ready的区别

说明(2017.4.2): 1. 在body中放一个img标签,src链接一张图片,那么页面会先读取html的document文档,然后再读取外部资源(这里没加onload其实就是从上往下顺序读取). 外部资源包括导入的js,css,图片,音乐,视频等等. onload会将所有的资源包括外部资源全部加载完成. 而jquery的ready只要加载完dom树就完成了,里面的图片等资源有没有加载无所谓. 1 <body> 2 <img src="1.jpg"> 3 &

JavaScript高级 面向对象(5)--最简单的继承方式,混入mix

说明(2017.3.30): 1. 最简单的继承方式,混入mix 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 </head> 7 <body> 8 <script type="text/javascrip

JavaScript基础——面向对象的程序设计(二)继承

继承是OO语言中的一个最为人津津乐道的概念.许多OO语言都支持两种继承方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.如前所述,由于函数没有签名,在ECMAScript中无法实现接口继承.ECMAScript只支持实现继承,而且实现继承主要是依靠原型链来实现的. 原型链 ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法.其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法.简单回顾以下构造函数.原型和实例的关系:每个构造函数都有

《JavaScript高级程序设计》学习笔记(5)——面向对象编程

欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 本节内容对应<JavaScript高级程序设计>的第六章内容. 1.面向对象(Object-Oriented, OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.前面提到过,ECMAScript中没有类的概念,因此它的对象也与基于类的语言中的对象有所不同. ECMA-262把对象定义为:"无序属性的集合,其属性可以包含基本值.对象或者函数.