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 ...
随机推荐
- php 实现创建文件并追加数据
最近因为后台有其他事情忙,所以我最近又开始学习php的内容了. (不过话说回来从客户端写到后台的感觉还是很爽的,嘿嘿) 需求是这样:从前台发来一些信息,存成文本文档,以后再统一处理(比如,存入用户账户 ...
- android 圆角图片的实现
图片展示的时候总觉的直角的图片不好看?好办法来了!-- public class ToRoundCorner extends Activity{ public Bitmap toRoundCorner ...
- mybatis Generator配置文件详解
这里按照配置的顺序对配置逐个讲解,更细的内容可以配合中文文档参照. 1. 配置文件头 <?xml version="1.0" encoding="UTF-8&quo ...
- __getattribute__
class Foo: def __init__(self,x): self.x = x def __getattribute__(self, item): print('不管是否纯在,我都会执行') ...
- RabbitMQ 路由选择 (Routing)
让日志接收者能够订阅部分消息.例如,我们可以仅仅将致命的错误写入日志文件,然而仍然在控制面板上打印出所有的其他类型的日志消息. 1.绑定(Bindings) 在前面中我们已经使用过绑定.类似下面的代码 ...
- 用一条sql语句显示数据百分比并加百分号
来源于:http://neil-han.iteye.com/blog/1948124 求数值所占比重 关键点:(round(t1.cnt/t2.totalCount*100,2))||'%'
- html5 css3中的一些笔记
<!DOCTYPE html> <html> <head> <meta charset="utf-8" > <title> ...
- 【转】向HTML中插入视频并兼容所有浏览器的方法
原文地址:http://www.jb51.net/web/168548.html 向HTML中插入视频有两种方法,一种是古老的object标签,一种是html5中的video标签,前者兼容性相对好些, ...
- Android 用代码设置Shape,corners,Gradient
网上查找资料 记录学习 int strokeWidth = 5; // 3dp 边框宽度 int roundRadius = 15; // 8dp 圆角半径 int strokeColor = Col ...
- Maven-搭建普通maven项目
点击Eclipse菜单栏File->New->Ohter->Maven得到如下图所示对话框: 选中Maven Project并点击Next,到下一个对话框(默认)继续点击Next得到 ...