【红宝书】第6章.面向对象的程序设计

面向对象(Object-Oriented,OO)

6.1理解对象

创建Object的实例,然后添加属性和方法

let person = new Object();

person.name = "AAA";

person.sayName = function() {};

对象字面量模式

let person = {

name: "AAA",

sayName: function() {}

};

6.1.1属性类型

用特性(attribute)描述属性(property)的各种特征

两种属性:1.数据属性2.访问器属性

1.数据属性

[[configurable]]:能否delete属性后从而重定义属性,能否修改属性的特性,能否把属性修改为访问器属性。默认true。改为false后不可逆。

[[enumerable]]:能否for-in循环返回属性。默认true。

[[writable]]:能否修改属性的值。默认true。

[[value]]:属性的数据值。默认undefined。

let person={name:’AAA’},如此直接定义时特性取默认值和数据值。

1.访问器属性

[[configurable]]:能否delete属性后从而重定义属性,能否修改属性的特性,能否把属性修改为访问器属性。默认true。改为false后不可逆。

[[enumerable]]:能否for-in循环返回属性。默认true。

[[get]]:读取属性时调用的函数。默认undefined。

[[set]]:写入属性时调用的函数。默认undefined。

6.1.2定义属性的特性

定义单个

Object.defineProperty(obj, property, descriptor); // descriptor 描述符

descriptor = {

configurable: true,

enumerable: true,

writable: true,

value: "example"

};

定义多个

Object.defineProperties(obj, {

property: {

configurable: true,

enumerable: true,

get: function() {},

set: function() {}

}

});

6.1.3读取属性的特性

Object.getOwnPropertyDescriptor(obj,property)

Object.getOwnPropertyDescriptors()

6.2创建对象

6.2.1工厂模式

用函数来封装以特定接口创建对象的细节

function createPerson(name) {

let obj = {

name: name,

sayName: function() {

alert(this.name);

}

};

return obj;

}

let person1 = createPerson("lpr");

虽然解决了多个相似对象的问题,但却没有解决对象识别的问题(即怎么知道一个对象的类型)

6.2.2构造函数模式

function Person(name) {

this.name = name;

this.sayName = function() {

alert(this.name);

};

}

let person1 = new Person("lpr");

let person2 = new Person("lpd");

跟工厂模式的不同:

  1. 没有显示的创建对象
  2. 直接将属性和方法赋给了this对象
  3. 没有return语句
  4. 函数名Person使用的是大写P(构造函数以大写字母开头,非构造函数以小写)

改造函数实际经历4个步骤

  1. 创建一个新对象
  2. 将构造函数的作用于赋给新对象,即this指向这个新对象
  3. 执行构造函数中的代码,即为新对象添加属性和方法
  4. 返回新对象

这样创建的对象都有一个constructor(构造函数)属性,该属性指向Person

person1.constructor===person2.constructor===Person

person1 instanceof Object // true

person1 instanceof Person // true

意味着可以将它的实例表示为一种特定的类型,但是其中的方法不是同一个Function实例

解决方案:

function Person(name) {

this.name = name;

this.sayName = sayName();

}

function sayName() {

alert(this.name);

}

这样做确实解决了两个函数做同一件事的问题,新问题:1.全局定义的方法直给某一个对象调用,全局作用域名不副实2.多个方法多次在全局定义函数,没有封装性

6.2.3原型模式

function Person() {}

Person.prototype.name = "AAA";

Person.prototype.sayName = function() {};

let person1 = new Person();

let person2 = new Person();

person1.sayName===person2.sayName

Person.prototype.isPrototypeOf(person1); // true

Object.getPrototypeOf(person1) === Person.prototype; // true

2.原型与in操作符

person1.hasOwnProperty("name"); // 是否自身存在属性

alert("name" in person1); // 属性是否存在于自身或原型中

可组合判断属性存在实例还是原型中

Object.keys(obj); // 获取对象上所有可枚举的实例属性,返回结果是key的数组

Object.getOwnPropertyNames(); // 获取对象上所有的实例属性,无论是否可枚举,如‘constructor‘

3. 更简单的原型语法

function Person() {}

Person.prototype = {

constructor: Person,

// 每创建一个函数会同时创建它的prototype对象,这个对象也会自动获取constructor属性。

// 如果不重新指定,即实例的constructor不指向Person

// 即person1.constructor !== Person,因此要重新指定建立联系

// 不过这种方式会使constructor属性的特性[[Enumerable]]为true,变为可枚举

name: "AAA",

sayName: function() {

console.log(this.name);

}

};

Object.defineProperty(Person.prototype, "constructor", {

enumerable: false,

value: Person

});

4. 原型的动态性

重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系

3. 原生对象的原型

不推荐修改原生对象的原型

4. 原型对象的问题

例如原型中有个属性时数组,在实例中push,则添加到了原型中的数组里。即变成共享。

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

构造函数定于实例属性,原型模式定于方法和共享方法。

每个实例都有自己的一份实例属性,又同时共享对方法的应用。是使用最广泛、认同度最高的创建自定义类型的方法。

6.3继承

6.3.1原型链

function SuperType() {

this.property = true;

}

SuperType.prototype.getSuperValue = function() {

return this.property;

};

function SubType() {

this.subproperty = false;

}

SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function() {

return this.subproperty;

};

let instance = new SubType();

alert(instance.getSuperValue()); // true

1. 默认原型

最顶层的原型为Object.prototype

1. 确定原型和实例的关系

instance instanceof Object

instance instanceof SuperType

instance instanceof SubType

都为true

Object.prototype.isPrototypeOf(instance)

SuperType.prototype.isPrototypeOf(instance)

SubType.prototype.isPrototypeOf(instance)

都为true

2. 谨慎定义方法

给原型添加方法的代码一定要放在替换原型的语句之后

通过原型链实现继承时,不能使用对象字面量创建原型方法。因为这样做会重写原型链

3. 原型链的问题
  1. 原型对象的问题
  2. 创建子类型的实例时,不能向超类型的构造函数中传递参数。即没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。

6.3.2借用构造函数(伪造对象或经典继承)

function SuperType() {

this.color = ["red", "green", "blue"];

}

function SubType() {

SuperType.call(this); //借调了超类型的构造函数

}

  1. 传递参数

function SuperType(name) {

this.name = name;

}

function SubType() {

SuperType.call(this, "lpr");

}

6.3.3组合继承

function SuperType(name) {

this.name = name;

this.color = ["red", "green", "blue"];

}

SuperType.prototype.sayName = function() {

alert(this.name);

};

function SubType(name, age) {

SuperType.call(this, name);

this.age = age;

}

SubType.prototype = new SuperType();

SubType.constructor = SubType;

SubType.prototype.sayAge = function() {

alert(this.age);

};

let instance1 = new SubType("lpr", 17);

instance1.color.push("black"); // ["red", "green", "blue","black"]

instance1.sayName(); // ‘lpr‘

instance1.sayAge(); // 17

let instance2 = new SubType("lpd", 16);

instance2.color; // ["red", "green", "blue"]

instance1.sayName(); // ‘lpd‘

instance1.sayAge(); // 16

6.3.4原型式继承

6.3.5寄生式继承

6.3.6寄生组合式继承

原文地址:https://www.cnblogs.com/Mijiujs/p/12080348.html

时间: 2024-08-02 21:37:23

【红宝书】第6章.面向对象的程序设计的相关文章

OPENGL 红宝书实验笔记

第一个程序triangles的配置过程,原文链接. OpenGL的东西快忘光了,把角落的第八版红宝书拿出来复习一下 从书中的地址下了个示例代码结果新系统(Win10+VS2015)各种跑不起来,懊恼之后在网上疯狂搜索资料终于跑起来了,记录一下 一.环境搭建指南 书中的地址 http://www.opengl-redbook.com/ 去这里打包下载OpenGL红宝书的示例代码,解压后是这样 虽然没有第一章的代码但第一章的内容好歹算一个完整的例子,网上各种环境搭建教程也都以第一章的代码为例,我们就

【转载】关于在vs2013中配置opengl红宝书第八版环境

 本文为转载 原文地址 http://blog.csdn.net/qq821869798/article/details/45247241 本人刚开始学习opengl,买了一本opengl红宝书第八版, 第一个例子研究了一段时间终于可以运行了,不知道有没有童鞋跟我遇到一样的问题. 下面说说我怎么配置的: 首先去 http://www.opengl-redbook.com/ 下载红宝书的源代码,解压得到这个 然后打开vs2013新建一个空的win32控制台项目, 然后点项目右键属性,点击vc++目

VS2012通过makefile编译OpenGL红宝书的示例代码

> 通过创建新VC项目,然后设置一堆属性,对于懒人来说还是太复杂了.既然它自带了makefile,可以尝试下使用nmake. 需要注意的是VS2012的安装目录里面已经没有GL的头文件和库文件.这个改动应该在VS2010或者更早就已经采用了. 现在有了VS SDK.VS2010自动的SDK目录是C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A,更高的版本可能使用v8.0.v8.0A,反正都在这个目录下面.这个目录下面有include.lib文

熬了多少个夜晚,大家期待的《网络工程师思科华为华三实战案例红宝书》即网工必备技术命令大全版本1完书

熬了多少个夜晚,最近也没空更新博客.军哥编写的大家期待的<网络工程师思科华为华三实战案例红宝书>即网工必备技术命令大全版本1完书,一本融合了思科华为华三的实战型辅导书(辅助乾颐堂QCNA课程的).不多说上图 目录关于作者 2本书读者和笔者心语 3本书内容和结构 4第1部分 网络实施基础 15案例0 模拟器的部署和连接管理 16学习利器模拟器简书 160.1 华为模拟器Ensp部署 160.2 思科模拟器EVE部署 310.3 部署SecureCrt管理网络设备 400.3.1 部署终端管理软件

js红宝书总结笔记

一.JS的简介: 1.宿主环境:浏览器.node.adobe flash; 2.DOM(文档对象模型)是针对 XML 但经过扩展用于 HTML 的应用程序编程接口(API): DOM0级:即DHTML:    DOM1级:主要映射文档结构: DOM2级:增加视图,样式,事件,遍历和范围: DOM3级:增加验证等方法: 3.BOM(浏览器对象模型) 二.在html中使用js 1.script的属性:defer(html4.01):脚本延迟至页面加载完成后执行:async(html5):不必等待脚本

红宝书 ECMAScript笔记

HTML中使用JS .基本概念 今天的JavaScript拥有了闭包.匿名函数.元编程等特性.它简单又复杂! 组成要素: 文档模式 严格模式 顶部加   关键字和保留字 关键字: 保留字: 函数内部的变量如何当作全局变量使用:(曾经要用到这个知识当时找不到答案)但是不推荐. typeof操作符 前置 与 后置的区别: ==(数值)与===(数值+类型)的区别 不允许用with 所有变量必须声明, 赋值给为声明的变量报错,而不是隐式创建全局变量. eval中的代码不能创建eval所在作用域下的变量

[OpenGL红宝书]第一章 OpenGL概述

第一章 OpenGL概述 标签(空格分隔): OpenGL 第一章 OpenGL概述 1 什么是OpenGL 2 初识OpenGL程序 3 OpenGL语法 4 OpenGL渲染管线 41 准备向OpenGL传输数据 42 将传输数据到OpenGL 43 顶点着色 44 细分着色 45 几何着色 46 图元装配 47 剪切 48 光栅化 49 片元着色 410 逐片元的操作 5 第一个程序深入分析 51 进入main函数 52 OpenGL的初始化过程 初始化顶点数组对象 分配顶点缓存对象 将数

【红宝书】第8章.BOM

浏览器对象模型,用于访问浏览器的功能.W3C为了把浏览器中JS最基本的部分标准化,已将BOM的主要方面纳入HTML5规范. 8.1 window对象 BOM的核心,表示浏览器实例.在浏览器中,window对象即是通过JS访问浏览器窗口的一个接口,又是ECMAScript规定的Global对象. 8.1.1全局作用域 由于window对象扮演着ECMAScript中的Global对象,所有在全局作用域中声明的变量.函数都会变成window对象的属性和方法. 全局变量不能通过delete操作符删除,

【红宝书】第7章.函数表达式

定义函数的方法两种 函数声明 function fnName(arg0, arg1, arg2) { //函数体 } 重要特征:函数声明提升 函数表达式 let fnName = function(arg0, arg1, arg2) { //函数体 } 即创建一个匿名函数(因为function关键字后面没有标识符)赋值给变量fnName 使用前必须先赋值 7.1递归 递归函数是一个函数通过名字调用自身的情况下构成的 function fn(num) { if (num <= 1) { retur