js006-面向对象的程序设计
js006-面向对象的程序设计
面向对象(Object-Oriented,OO)的语言有一个标志,那就是他们都有类的概念。而通过类可以创建多个具有相同属性和方法的对象。
ECMA-262把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。(对象是一组没有特定顺序的值)。对象每个方法或者属性都有一个特定的名字,每个名字都映射到一个特定的值。对象可以想象为一个散列表,一组名值对,其中之可以是数据或者函数。
每个对象都是基于一个引用类型创建的。
6.1理解对象
创建自定义对象的最简单凡事就是创建一个Object的实例,再为它添加属性和方法。
|
var person = new Object(); person.name = "meimei"; person.age = 18; person.job = "software enginer"; person.sayName = function(){ alert(this.name); }; |
创建了一个名为person的对象,添加三个属性并对其赋值,和一个方法sayName用于显示this.name |
6.1.1属性类型
ECMAScript中有两种属性:数据属性和访问器属性
数据属性:包含一个数据值的位置,这个位置可以读取和写入值。一下四个特性描述数据属性的行为
|
[[Configurable]] |
表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。默认值为:true |
|
[[Enumerable]] |
表示能否通过for-in循环返回属性。默认值为:true |
|
[[Writable]] |
表示能否修改属性的值。默认值为:true |
|
[[Value]] |
包含这个属性的数据值,读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存到这个位置,这个特性的默认值为Undefined |
要修改属性的默认特性必须使用Object.defineroperty()方法。该方法接收三个参数:属性所在的对象,属性的名字和一个描述符对象。描述符对象的属性必须是:Configurable、Enumerable、Writable、Value,设置其中的一个或者多个值,可以修改其默认值。
访问器属性:访问器属性不包含数据值;它包含一对getter和setter函数(这两函数都不是必须的)
|
getter函数 |
读取访问器属性时调用,返回有效值 |
|
setter函数 |
写入访问器属性是调用,传入新值 |
访问器属性有以下四个特性:
|
[[Configurable]] |
表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。默认值为:true |
|
[[Enumerable]] |
表示能否通过for-in循环返回属性。默认值为:true |
|
[[Get]] |
读取访问器属性时调用的函数,默认值为:Undefined |
|
[[Set]] |
写入访问器属性是调用的函数,默认值为:Undefined |
访问器属性不能直接定义,必须使用Object.defineProperty()来定义:
|
var book = { _year: 2015, _edition:1 }; Object.defineProperty(book, "year", { get:function(){ if (newValue > 2015) { this.year = newValue; this.edition += newValue - 2015; } } }); book.year = 2016; alert(book.edition); //2 |
创建了一个book对象,并定义了连个默认属性, _(添加下划线)表示只能通过对象访问的属性。 |
6.1.2定义多个属性
通过Object.defineProperties()方法可以依稀定义多个属性。该方法接收两个参数,第一:对象要添加及修改其属性的对象;第二对象的属性与第一个对象中要添加或修改的属性一一对应。
如
|
var book ={}; Object.defineProperties(book,{ _year:{ writable:true, value:2015 }, edition:{ value:1 }, year:{ get.function(){ return this._year; }, set:function(newValue){ if (newValue > 2015) { this.year = newValue; this.edition += newValue - 2015; } } } }); |
定义了个book独享的两个数据属性_year和edition和一个访问器属性(year).最终的对象与上一节中定义的对昂相同,唯一的区别是这里的属性都是在同一时间创建的。 |
6.1.3读取属性的特性
|
var book ={}; Object.defineProperties(book,{ _year:{ value:2015; }, edition:{ value:1 }, year:{ get:function(newValue){ if (newValue > 2015) { this._year = newValue; this.edition += newValue - 2015; } } } }); var descriptor = Object.getOwnPropertyDescriptor(book, "_year"); alert(descriptor.value); //2015 alert(descriptor.configurable); //false |
使用Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符,该方法接收两个参数:属性所在的对象和要读取其描述符的属性的名称。返回值是一个对象,如果是访问器属性,这个对象的属性有:Configurable、Enumerable、Get、Set 如果是数据属性,这个对象的属性有:Configurable、Enumerable、Writable、Value |
6.2 创建对象
工厂模式的一个变体是为了解决Object构造函数或者对象字面量创建单个对象的缺点:使用同一个借口创建很多对象,会产生大量的重复代码。
6.1.1 工厂模式
这种模式抽象了创建具体对象的过程。因为ECMAScript中无法创建类,所以用函数来封装特定接口创建对象的细节。
例子:
|
function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; } var person1 = createPerson("meimei", 18, "teacher"); var person2 = createPerson("lal-Alice", 18, "software enginer"); |
可以多次调用createPerson()函数 在控制台运行并测试: console.log(person2); Object {name: "lal- Alice", age: 18, job: "software enginer"} 但是工程模式没有解决对象识别的问题(怎样知道一个对象的类型) |
6.2.2构造函数模型
像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中。可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。例如:可以使用构造函数模式将前面的例子重写如下:
|
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; o.sayName = function(){ alert(this.name); }; } var person1 = new Person("meimei", 18, "teacher"); var person2 = new Person("lal", 18, "software enginer"); |
Person()取代了createPerson()函数。相对来说不同的是:Person()中 1、没有显式地创建对象; 2、直接将属性和方法赋给了this对象; 3、没有return语句。 |
构造函数(只要是通过new操作符来调用的,它就可以作为构造函数)的首字母一般为大写字母。非构造函数应该以一个小写字母开头。这样主要是为了区别于ECMAScript中的其他函数;因为构造函数本身也是韩式,不过,它可以用来创建对象。。
要创建一个Person新实例,必须使用new操作符。以这种方式调用构造函数会经历以下4个步骤:
|
创建一个新对象 |
|
将构造函数的作用域赋给新对象 |
|
执行构造函数中的代码(添加新属性) |
|
返回新对象 |
person1和 person2分别保存person的一个不同实例。它们都有一个属性:constructor(构造函数),该属性指向person。该属性是用来标识对象类型的。对于对象类型检测最好还是用:instanceof操作符。
1、将构造函数当做函数。
之前的Person()函数可以通过以下任意一种方式来调用
|
当做构造函数使用 |
var person2 = new Person("lal-Alice", 18, "software enginer"); person.sayName();//"lal-Alice" |
|
作为普通函数调用 |
person("lal-Alice" , 18, "software enginer"); window.sayName();//"lal-Alice" |
|
在另一个对象的作用域中调用 |
var o = new Object(); Person.call(o, "lal-Alice", 18, "software enginer"); o.sayName();//"lal-Alice" |
2、构造函数的问题
主要问题:每个方法都要在每个实例上重新创建一遍。
6.2.3原型模式
我们创建的每个函数都有一个原型属性,这个属性是一个指针,,指向一个对象。
(该部分笔记,之后补上来,先认真看书。2016/1/20 15:41)
6.2.4组合使用构造函数模式和原型模式
创建自定义类型的最常见的方式就是组合使用构造函数模式和原型模式。构造函数模式用于定义实例属性,原型模式用于定义方法和共享属性。结果:每个实例都有自己的一份实力属性副本,同时又共享着对方法的引用,最大限度的节省了内存。
如下代码:
|
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.fiiends = ["shelby", "Court"]; } Person.prototype = { constructor:person; sayName:function(){ alert(this.name); } } var person1 = new Person("meimei", 18, "teacher"); var person2 = new Person("lal", 18, "software enginer"); person1.fiiends.push("van"); alert(person1.fiiends); //"shelby,Court,van" alert(person2.fiiends); //"shelby,Court" alert(person1.fiiends == person2.fiiends); //false alert(person1.sayName == person2.sayName); //true |
|
实例属性是在构造函数中定义的,而由所有实例共享的属性constructor和方法sayName()则是在原型中定义的。而修改了person1.fiiends,并不会影响到person2.fiiends |
6.2.5动态原型模式
可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。例如:
|
function Person(name, age, job){ //属性 this.name = name; this.age = age; this.job = job; //方法 if (typeof this.sayName != "function") { Person.prototype.sayName = function(){ alert(this.name); } }; } var friend = new Person("lal-Alice" , 18, "software enginer"); friend.sayName(); |
|
加粗代码只有在sayName()方法不存在的情况下,才会添加到原型中,这段代码只有在初次构造函数时才会调用。 |
6.2.6寄生构造函数
之前的集中模式都不适用的情况下可以使用寄生(parasitic)模式。它的基本思想是创建一个函数,作用是封装创建对象的代码,然后再返回新创建的对象。
6.2.7寄生构造函数
所谓稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象。
(版权声明:该博客为http://www.cnblogs.com/lal-fighting/原创发表,未经允许,不得转载或抄袭!!! )
6.3 继承
一般有两种继承方式:借口继承和实现继承。
ECMAScript只支持实现继承,而实现继承主要是通过原型链来实现的。
6.3.1原型链
基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法。
实现原型链有一种基本模式,其代码大致如下:
|
//原型链 function SupperType(){ this.property = true; SupperType.property.getSuperValue = function(){ return this.property; }; } function SubType(){ this.subproperty = false; } //继承了SuperType SubType.propertype = new SupperType(); SubType.propertype.getSuperValue = function() { return this.subproperty; }; var instance = new SupperType(); alert(instance.getSuperValue()); //true |
|
定义了两个类型:SuperType SubType。每个类型分别有一个属性和一个方法。 |
(未完成,笔记之后补上)
1、别忘记默认的原型
2、确定原型和实例的关系
3、谨慎地定义方法
6.3.2借用构造函数
也叫伪造对象或经典继承。
基本思想:在子类型构造函数的内部调用超类型构造函数。通过apply() 和call()方法也可以再新创建的对象上执行构造函数(将来)
1、传递参数:相对于原型链而言,借用构造函数有一个很大的优势,可以在子类型构造函数中向抄类型构造函数传递参数。
2、借用构造函数的问题:无法避免构造函数模式存在的问题—方法都在构造函数中定义,所以函数没法复用。而且,在超类型的原型定义的方法,对子类型而言是不可见的。结果所有类型都只能使用构造函数模式
6.3.3组合继承 (最常用的继承)
也叫伪经典继承,指的是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。
思路:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,,成为javaScript中最常用的继承
(笔记未更新上来)
6.3.4原型式继承
6.3.5寄生式继承
6.3.6寄生组合式继承
版权声明:该博客为http://www.cnblogs.com/lal-fighting/原创发表,未经允许,不得转载或抄袭!!!
js006-面向对象的程序设计的更多相关文章
- 【Python3之面向对象的程序设计】
一.面向对象的程序设计的由来 1.第一阶段:面向机器,1940年以前 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数据. 简单来说,就是直接编写 0 和 1 ...
- Python进阶---面向对象的程序设计思想
Python的面向对象 一.面向过程与面向对象的对比 面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优 ...
- python 面向对象的程序设计
一:什么是编程范式? 编程是程序员用特定的语法 + 数据结构 + 算法组成的代码来告诉计算机如何执行任务的过程. 如果把编程的过程比喻为练习武功,那么编程范式指的就是武林中的各种流派,而在编程的世界里 ...
- python基础——面向对象的程序设计
python基础--面向对象的程序设计 1 什么是面向对象的程序设计 面向过程的程序设计的核心是过程,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优 ...
- javascript高级程序设计第3版——第6章 面向对象的程序设计
第六章——面向对象的程序设计 这一章主要讲述了:面向对象的语言由于没有类/接口情况下工作的几种模式以及面向对象语言的继承: 模式:工厂模式,构造函数模式,原型模式 继承:原型式继承,寄生式继承,以及寄 ...
- python学习------面向对象的程序设计
一 面向对象的程序设计的由来 1940年以前:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数 据.简单来说,就是直接编写 和 的序列来代表程序语言 ...
- Python之路【第八篇】:面向对象的程序设计
阅读目录 一 面向对象的程序设计的由来二 什么是面向对象的程序设计及为什么要有它三 类和对象3.1 什么是对象,什么是类3.2 类相关知识3.3 对象相关知识3.4 对象之间的交互3.5 类名称空间与 ...
- python之面向对象的程序设计
一.什么是面向对象的程序设计 面向过程的程序设计的核心是过程,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优点是:极大的降低了程序的复杂度 缺点是: ...
- python之旅:面向对象的程序设计
一 面向对象的程序设计的由来 面向对象设计的由来见概述:http://www.cnblogs.com/moyand/p/8784210.html 二 什么是面向对象的程序设计及为什么要有它 面向过程的 ...
- python基础----面向对象的程序设计(五个阶段、对小白的忠告、关于OOP常用术语)、类、对象
一.面向对象的软件开发有如下几个阶段 1.面向对象分析(object oriented analysis ,O ...
随机推荐
- bat批处理文件启动Eclipse和ivy本地仓库的配置
一.bat批处理文件启动Eclipse 所需文件: 1.eclipse 2.jre 3.startup-eclipse.bat 确保以上三个文件夹同级 startup-eclipse.bat: set ...
- hihocoder 1260
之前做过的oj, acm题目忘了很多了, 又要开始要刷题了, go on! #1260 : String Problem I 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描 ...
- linux初级,连网
第一次写,今天刚好装上centos,然后就玩装一些软件,但要联网,所以琢磨了半天连网,下面总结下今天积累的一些知识点吧! 首先需要查看电脑有没有装驱动:ifconfig -a, 看有没有eh0(网卡) ...
- yii2搭建完美后台并实现rbac权限控制实例教程
1.安装yii2 未安装的请参考yii2史上最简单式安装教程,没有之一 或者参考yii2实战教程之详细安装步骤 已安装的请继续看下一步操作 2.配置数据库 2.1 配置数据库 修改common/con ...
- eclipse的插件安装
如何安装:http://my.oschina.net/linjunlong/blog/126961 插件安装方法:eclipse和myeclipse版本不一样,略有区别 在线安装: 第一种:知道在线安 ...
- Percona 开始尝试基于Ceph做上层感知的分布式 MySQL 集群,使用 Ceph 提供的快照,备份和 HA 功能来解决分布式数据库的底层存储问题
本文由 Ceph 中国社区 -QiYu 翻译 英文出处:Using Ceph with MySQL 欢迎加入CCTG Over the last year, the Ceph world drew m ...
- 【BZOJ 1038】【ZJOI 2008】瞭望塔
http://www.lydsy.com/JudgeOnline/problem.php?id=1038 半平面交裸题,求完半平面后在折线段上的每个点竖直向上和半平面上的每个点竖直向下求距离,统计最小 ...
- ELK系统中kibana展示数据的时区问题
在采用ELK记录系统日志时,日志存入elasticsearch时,一般是以本地时区存入(如北京东8区) 在elasticsearch中直接查询时也没有任何问题,但是kibana在做日志展示时,对日志时 ...
- Win7另存文件没有桌面的解决方法
今日一朋友保存文件随口说了一句我那个桌面找不到了...我略感惊奇,没遇到这么个情况.决定,问度娘,在此做下记录,以便以后自己或朋友查阅. 我们在网上另存一个文件,打开另存窗口,发现没有“桌面” 在收藏 ...
- Java面试知识的认知描述
连接池:同时操作连接数据库,创建一个连接池,池子里创建一万个数据库链接.根据系统运行情况关闭链接.高峰期链接达到最大MAX进行排队,对在用的链接实现失效时间.有几种:tomcat请求服务器(serve ...