<读书笔记>JavaScript系列之7种创建对象(面向对象)
写在前面:
以下三选一:
- 阅读博文JavaScript 对象详解.
- 阅读《JavaScript权威指南》第6章。
- 阅读《JavaScript高级程序设计》第6章。
- 注意:只需要看“理解对象”(Understanding Objects)部分。
6.2 创建对象
6.2.1 工厂模式
- 创建多个相似对象的问题,代码实现
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("tianyuan", 22, "web-front-end");
var person2 = createPerson("zhangsen", 21, "analysis");
alert(person1.name);
alert(person2.sayName());
6.2.2 构造函数模式
三个特点:
- 1.没有显示地创建对象
- 2.直接将属性和方法赋给了this对象
- 3.没有return语句
- ⚠️注意:构造函数命名:开头大写
代码实现:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
alert(this.name);
};
}
var person1 = new Person("tianyuan", 22, "web-front-end");
var person2 = new Person("zhangsen", 21, "analysis");
console.log(person1.name);
console.log(person2.sayName());
alert(person1.constructor == Person);
alert(person2.constructor == Person);
alert(person1 instanceof Object); // 检查person1是否是否为Objetct的实例, Objetct注意首位大写
alert(person1 instanceof Person); // 检查person1是否是否为Person的实例
alert(person2 instanceof Object); // 检查person2是否是否为Objetct的实例, Objetct注意首位大写
alert(person2 instanceof Person); // 检查person2是否是否为Person的实例
6.2.3 原型模式
每个函数都有一个prototype(原型)属性.
1.prototype:
- 这个属性是一个指针: [[Prototype]];
- 通过调用构造函数而创建的那个对象实例的原型对象
- 使用其的好处是: 可以让所有对象实例共享它所包含的属性和方法.
- 也就是说:不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中.
- 与构造函数不同的是: 其新对象的这些属性和方法是由所有实例共享的.
- 这里需要理解原型对象,才能理解这种模式的原理.
- __ proto __
- p148 图解,秒懂
- 原理: 原型对象是真实存在的,而person1,person2的prototype则是以虚拟的指针形式来引用真实的原型对象以达到共享属性和方法的目的.
- isPrototypeOf()用来确定对象之间是否存在这种原型关系.
- Object.getPrototypeOf,这个方法返回:[[Prototype]](ECMAScript 5 新增的方法)
- delete操作符,实例属性会屏蔽原型中的同名属性,除非使用delete操作符删掉实例属性.
- hasOwnProperty: 实例属性返回true, 原型属性则返回false
2.in操作符与原型
- in操作符: alert("name" in person); //true or false
- hasPrototypeProperty()函数
- in: IE早期版本 bug
- Object.keys()
- Object.getOwnPropertyNames(): 无论是否可以枚举,可得到所有实例属性.
- 15,16皆可代替for-in循环枚举
3.更简单的原型语法:
- 提取prototype至于person后() {},代码如下
- 简单版的字面量创建对象的方法会导致constructor不再指向Person
- 通过设定将constructor值改为: Person后,会导致它的[[Enumerable]]被设置为true.
- 重设构造函数(只适用于ECMAScript兼容的浏览器)
function Person() {
}
Person.prototype = {
name : "tianyuan",
age : 29,
job: "web",
sayName: function() {
alert(this.name);
}
};
4.原型的动态性
5.原生对象的原型
- 可自定义方法:startWith()
6.原型对象的问题:
- 共享的话,一旦改,则全变,从而无法单独使用此模式,需要结合构造函数模式.
代码实现:
function Person() {
}
Person.prototype.name = "tianyuan";
Person.prototype.age = 29;
Person.prototype.sayName = function() {
alert(this.name);
}
var person1 = new Person();
var person2 = new Person();
person1.sayName();
person2.sayName();
var keys = Object.keys(Person.prototype); // 通过原型调用
alert(keys); // "name, age, job, sayName" 可枚举属性
var p1 = new Person();
p1.name = "Rob";
p1.age = 31;
var p1keys = Object.keys(p1); // 通过实例调用
alert(p1keys); // "name, age" 可枚举属性
// 在此种模式中,false问题得以解决;且新对象的这些属性和方法是由所有实例共享的.
alert(person1.sayName == person2.sayName); //true
6.2.4 组合使用构造函数模式和原型模式
这是结合两种模式的长处所成的一个成熟模式
优点:
- 每个实例都会有自己的一份实例属性的副本
- 同时又共享着对方法的引用
- 最大限度地节省了内存。
代码实现:
// 混合模式重写例子
// 这是目前ECMAScript中使用最广泛,认同度最高的一种创建自定义类型的方法,可以说是定义引用类型的默认模式.
function Person(name, age, job) {
this.name = name;
this.job = job;
this.age = age;
this.friends = ["tianyuan", "zhangsen"];
}
Person.protptype = {
constructor : Person, // 指向Person原型
sayName : function() {
alert(this.name);
}
};
var person1 = new Person("tianyuan", 22, "web-front-end");
var person2 = new Person("zhangsen", 21, "analysis");
person1.friends.push("Van");
alert(person1.friends); // tianyuan,zhangsen,Van
alert(person2.friends); // tianyuan,zhangsen
alert(person1.friends === person2.friends); // false
alert(person1.sayName === person2.sayName); // true
6.2.6 寄生构造函数模式
代码实现类似于: 工厂模式与构造函数模式的结合体
总的来说,建议在可以使用其它模式的情况下,不要使用此模式.
instanceof 操作符对此对象无意义
代码实现:
function Person(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 friend = new Person("tianyuan", 18, "web");
friend.sayName(); // tianyuan*/
// 这个模式可以在特殊的情况下用来为对象创建构造函数.(因为不能直接修改Array构造函数)
function SpecifialArray() {
// 创建数组
var values = new Array();
// 添加值
values.push.apply(values, arguments);
// 添加方法
values.toPipedString = function() {
return this.join("|");
};
// 返回数组
return values;
}
var colors = new SpecifialArray("red", "ok", "blue");
alert(colors.toPipedString()); // "red|ok|blue"
6.2.7 稳妥构造函数模式
所谓的稳妥对象: 没有公共属性,且其方法也不引用this的对象.
稳妥对象最适合在一些安全的环境中(禁止使用this or new),或者在防止数据被其它应用程序改动时使用.
稳妥构造函数是与寄生构造函数类似的模式,但有2点不同: (1)新创建对象的实例方法不引用this. (2)不使用new操作符调用构造函数
变量friend中保存的是一个稳妥对象,且instanceof 操作符对此对象无意义
⚠️: 这种模式下,除了使用sayName()外,没有其它办法访问name值.
代码实现:
function Person(name, age ,job) {
var o = new Object();
// 可以在这里定义私有变量和函数
// 添加方法
o.sayName = function() {
alert(name);
}
// 返回对象
return o;
}
var friend = Person("tianyuan", 18, "web");
friend.sayName(); // tianyuan
定义访问器属性(新法)
var book = {
_year: 2004,
edition: 1
};
Object.defineProperty(book, "year", {
get: function() {
return this._year;
},
set: function(newValue) {
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
});
book.year = 2005;
alert(book.year);
alert(book.edition);
定义访问器属性(旧法)
var book = {
_year: 2004,
edition: 1
};
// 定义访问器的旧方法
book.__defineGetter__("year", function() {
return this._year;
});
// _ _ , 俩
book.__defineSetter__("year", function(newValue) {
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
});
book.year = 2005;
alert(book.year);
alert(book.edition);
Object.defineProperties
- 定义多个属性(合起来)
var book = {};
Object.defineProperties(book, {
_year: {
value: 2004
},
edition: {
value: 1
},
year: {
get: function() {
return this._year;
},
set: function(newValue) {
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
}
});
var descriptor = Object.getOwnPropertyDescriptor(book, "_year");
alert(descriptor.value);
alert(descriptor.configurable);
alert(typeof descriptor.get);
var descriptor = Object.getOwnPropertyDescriptor(book, "year");
alert(descriptor.value);
alert(descriptor.configurable);
alert(typeof descriptor.get);
对象字面量创建对象
// 对象字面量创建对象
var person = {
name: "TianYuan",
age: "22",
job: "web-front-end",
sayName: function() {
alert(this.name);
}
};
alert(person.name);
alert(person.age);
alert(person.sayName());
【Javascript高级程序设计 】
第三版
p25
对未经声明变量调用delete不会导致错误?
p27
布尔类型:0,NaN,null,undefined会转化为false
p29
Number.MAX_VALUE==1.7976931348623157e+308。Infinity。
isFinite()
isNaN()
Number()
parseInt()指定基数,
parseFloat()
p34拼接字符串过程
toString()
p37
var num1=2;
var num2=20;
var num3=num1-- + num2;//等于22
var num4=num1 + num2;//等于21
p38
一元操作符 a=+a //a
一元操作符 b=-b //-b
p40-26
p42按位异或XOR
p43左移右移各种
Boolean()
短路操作符false
p47.8skip
p57for-in 枚举
p58label语句需配合for循环p59循环
with()
2016.03.17.08:40
p69 不能给基本类型值添加属性,只能对象
<读书笔记>JavaScript系列之7种创建对象(面向对象)的更多相关文章
- <读书笔记>Javascript系列之6种继承(面向对象)
写在前面: 以下三选一: 阅读博文JavaScript 对象详解. 阅读<JavaScript权威指南>第6章. 阅读<JavaScript高级程序设计>第6章. 注意:只需要 ...
- Chrome插件安利!可以一键导出微信读书笔记|支持Markdown等三种格式
众所周知,微信读书App 是一款非常优秀的阅读类App ,周围也有不少人在用.虽然工作比较忙.但是也没少在上面看书做笔记. 美中不足的是,目前微信读书虽然支持笔记导出,但是提供的是将笔记复制到剪切板, ...
- JS学习笔记——JavaScript继承的6种方法(原型链、借用构造函数、组合、原型式、寄生式、寄生组合式)
JavaScript继承的6种方法 1,原型链继承 2,借用构造函数继承 3,组合继承(原型+借用构造) 4,原型式继承 5,寄生式继承 6,寄生组合式继承 1.原型链继承. <script t ...
- [读书笔记]javascript语言精粹'
人比较笨,以前只做项目,案例,然而一些javascript的很多理论不知道该怎么描述,所以最近开启一波读书之旅: 标识符 1.定义 标识符以字母开头,可能后面跟上一个或多个字母.数字或者下划线. 2. ...
- 读书笔记-JavaScript面向对象编程(三)
第7章 浏览器环境 7.1 在HTML页面中引入JavaScript代码 7.2概述BOM与DOM(页面以外事物对象和当前页面对象) 7.3 BOM 7.3.1 window对象再探(所以JavaSc ...
- [读书笔记] JavaScript设计模式: 单例模式
单例模式:保证一个类只有一个实例,并提供一个可以访问它的全局访问点. 一种简单.方便的写法就是用一个变量来标识当前类是否已经创建过对象,如果有,则返回已经创建好的对象,否则创建一个新对象,并将其返回. ...
- 读书笔记-----javascript基本数据类型
由于js基础差, 记性也不好,准备一边读书一边做记录,希望这样能加深一下记忆 /* 第一天 */ javascript 基本数据类型 js一共只有五种数据类型 Undefined, Nu ...
- 读书笔记-JavaScript面向对象编程(一)
PDF下载链接: http://pan.baidu.com/s/1eSDSTVW 密码: 75jr 第1章 引言 1.1 回顾历史 1.2 变革之风 1.3 分析现状 1.4 展望未来 1.5 面向对 ...
- 《JavaScript权威指南》读书笔记——JavaScript核心
前言 这本由David Flanagan著作,并由淘宝前端团队译的<JavaScript权威指南>,也就是我们俗称的“犀牛书”,算是JS界公认的“圣经”了.本书较厚(有1004页),读起来 ...
随机推荐
- 在Lua中进行运算符重载
在C++里面运算符是可以重载的,这一点也是C++比较方便的一个地方.在Lua中其实也是可以模拟出运算符的重载的. 在Lua中table中元素的运算都是和一个叫做元表有关的,在一个table型的变量上都 ...
- quartz CronExpression
一.Quartz Cron 表达式支持到七个域 名称 是否必须 允许值 特殊字符 秒 是 0-59 , - * / 分 是 0-59 , - * / 时 是 0-23 , - * / 日 是 1-31 ...
- vue.js2.0 (简易)水果商城 vuex vant-ui
vue.js2.0 (简易)水果商城 vuex vant-ui:https://segmentfault.com/a/1190000015690250 vue2.5全家桶 高仿vivo商城 百分之95 ...
- python 列表总结大全
1定义 names=[] names=[1,2,1,1,1,] names=[1.'10'.[1,1]] 2添加元素 names.append() names.insert(0,10) names.e ...
- c# 添加数据
/// <summary> /// 新增一条省份记录 /// </summary> /// <param name="model"></p ...
- CSS 实现水平垂直居中
使用绝对定位 在已经知道子元素的宽高的时候,子元素设置成绝对定位,top,left,right,bottom=0, margin = auto .wrap{ position: relative; w ...
- 为什么MySQL索引要使用 B+树,而不是其它树形结构?
作者:李平 https://www.cnblogs.com/leefreeman/p/8315844.html 一个问题? InnoDB一棵B+树可以存放多少行数据?这个问题的简单回答是:约2千万 为 ...
- 浏览器报406 错误:The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers
The resource identified by this request is only capable of generating responses with characteristics ...
- zabbix入门之配置邮件告警
zabbix入门之配置邮件告警 邮件环境搭建 使用本地邮箱账号发送邮件 zabbix-server 端安装 mailx .sendmail或者psotfix 服务,系统默认安装好了postfix #安 ...
- Git--07 Gitlab备份与恢复
目录 Gitlab备份与恢复 01). 备份 02). 恢复 Gitlab备份与恢复 对gitlab进行备份将会创建一个包含所有库和附件的归档文件.对备份的恢复只能恢复到与备份时的gitlab相同 ...