《Javascript高级程序设计》读书笔记——构造函数与原型
构造函数与原型
构造函数模式
最简单的构造函数:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
console.log(this.name);
}
}
var p1 = new Person("jerry", 18, "Coder");
var p2 = new Person("tom", 28, "Javaer");
要创建Person的实例,需要使用new关键字。以这种方式调用函数能够创建实例对象是因为使用new后会隐式地执行以下四个步骤:
- 创建一个新对象(基于Object的对象)
- 将构造函数的作用域赋给新对象(此时this就指向了新对象)
- 执行构造函数内的代码
- 返回对象
若不使用new关键字而直接调用该函数,那它就跟普通函数一样;函数中的this就会是当前的全局作用域:
Person("jerry", 18, "Javaer"); //添加到window中
window.sayName(); // "jerry"
实例对象都会有个constructor(实际上这个属性应该是在原型上的。下一节讲原型的概念)属性,指向构造函数:
console.log(p1.constructor == Person); //true
但不建议使用这种方式来检测对象类型,因为该属性是可写的;应使用instanceof。
原型模式
前面说的最基本的构造函数模式有个很明显的问题就是:对于每次新创建一个实例时,都需要在实例上重新创建一个sayName函数;这样创建许多相同功能的函数对象显然是没有必要的。下面说的原型模式可以解决这种问题。
在JS中创建的每一个函数类型都有一个prototype(原型)属性,该属性指向一个对象 即原型对象,而这个对象的用途是可以包含由某一类型的所有实例共享的属性和方法。
通过这个例子来辅助理解下原型的用途:
function Person() {
}
Person.prototype.name = "jerry";
Person.prototype.age = 18;
Person.prototype.job = "Javaer";
Person.prototype.sayName = function() {
console.log(this.name);
}
var p1 = new Person();
var p2 = new Person();
p1.sayName() //"jerry"
console.log(p1.sayName == p2.sayName) //true
通过在原型中定义变量和函数,使得该构造函数的所有实例都能共享相同的变量和函数。这是由原型搜索机制所完成的:因为每个实例对象都有个内部属性[[prototype]]指向原型对象;当搜索对象的某个属性时,会先搜索实例对象本身,如果有则返回;没有的话就会到[[prototype]]指针指向的原型中继续寻找。 因此,在实例对象中可以覆盖原型中的同名属性。 而且,所有实例对象指向的都是同一个原型,这也就是为什么上面代码中实例对象都有相同的变量和函数。
需要注意一点,实例对象的[[prototype]]是在创建对象初由构造函数的prototype属性赋值来的;所以 如果在创建完实例对象后重写原型的话,重写后的原型是与先前创建的实例对象无关的(实例对象仍指向原来的那个原型):
function Person() {
}
Person.prototype = {
constructor: Person,
name : "Tom"
}
var p = new Person();
console.log(p.name); //"Tom"
Person.prototype = {
constructor: Person,
name: "jerry",
age: 18,
job: "Javaer",
sayName: function() {
console.log(this.name);
}
}
console.log(p.name); //"Tom"
p.sayName(); //throw error
寄生构造函数模式
名字起的有些奇怪,其实就是指封装显式创建对象的过程,然后再返回新创建的对象。
function Person() {
var o = new Object();
o.name = "Java";
o.f = function() {
console.log("Kotlin");
}
return o;
}
var temp = new Person();
console.log(temp.name); //"Java"
temp.f(); //"Kotlin"
这里使不使用new操作符都没有影响,两者效果是一样的。使用了new,构造函数在无返回值的情况下,默认返回隐式创建的新实例对象。而在构造函数中添加return语句,可以重写调用构造函数时返回的值。
这种模式本质上讲就是用个普通函数 在其中对已有对象进行添加或重写属性 以达到增强已有对象的功能;还有点类似于继承的作用。
创建一个自定义的Array对象:
function myArray() {
var arr = new Array();
arr.push.apply(arr, arguments);
arr.toString = function() {
return this.join("|");
}
return arr;
}
var colors = myArray("red", "blue", "yellow");
console.log(colors.toString()); //"red|blue|yellow"
稳妥构造函数模式
这一节的内容在红宝书上放的位置感觉是不太合适的=_= ... 对于初学者看这节的内容可能会有点迷,而且书上给的例子的代码也不全。 书上阐述的这种模式的作用 主要就是为了构造没有公共属性的对象,即模拟 私有变量,仅能通过函数访问。 建议可以跳过这一节的内容,在之后明白了闭包的概念后可以再回来看下这节内容。
《Javascript高级程序设计》读书笔记——构造函数与原型的更多相关文章
- Javascript高级程序设计--读书笔记之理解原型对象
先上一段代码和关系图 function Person(){} Person.prototype.name = "Nic" Person.prototype.age = 22 Per ...
- JavaScript高级程序设计-读书笔记(2)
第6章 面向对象的程序设计 创建对象 1.最简单方式创建Object的实例,如 var person = new Object(); person.name = “Greg”; person.age ...
- javascript高级程序设计读书笔记-事件(一)
读书笔记,写的很乱 事件处理程序 事件处理程序分为三种: 1.html事件2. DOM0级,3,DOM2级别 没有DOM1 同样的事件 DOM0会顶掉html事件 因为他们都是属性 而 ...
- Javascript高级程序设计--读书笔记之面向对象(一)
哈哈哈万物皆对象,终于到了js的面向对象篇. 一.属性类型 (1)数据属性 数据属性包含一个数据值的位置,在这个位置可以写入和读取数值,数据属性有四个描述器行为的特性 [[Configurable]] ...
- javascript高级程序设计读书笔记
第2章 在html中使用javascript 一般都会把js引用文件放在</body>前面,而不是放在<head>里, 目的是最后读取js文件以提高网页载入速度. 引用js文 ...
- Javascript高级程序设计读书笔记(第六章)
第6章 面向对象的程序设计 6.2 创建对象 创建某个类的实例,必须使用new操作符调用构造函数会经历以下四个步骤: 创建一个新对象: 将构造函数的作用域赋给新对象: 执行构造函数中的代码: 返回新 ...
- JavaScript高级程序设计-读书笔记(7)
第22章 高级技巧 1.高级函数 (1)安全的类型检测 在任何值上调用Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串. ...
- javascript高级程序设计读书笔记----面向对象的程序设计
创建对象 工厂模式 function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = ...
- javascript高级程序设计 读书笔记1
第二章 在HTML中使用JS 加载JS有三种:行内,head头部和外部链接JS 最好使用外部链接<script src="example.js" ></sc ...
- JavaScript高级程序设计-读书笔记(6)
第20章 JSON JSON是一个轻量级的数据格式,可以简化表示复杂数据结构的工作量 JSON的语法可以表示一下三种类型的值 l 简单值:使用与JavaScript相同的语法,可以在JS ...
随机推荐
- openGemini v0.2.0版本正式发布:5大特性全面增强
摘要:openGemini是华为云面向物联网和运维监控场景开源的一款云原生分布式时序数据库,兼容InfluxDB API,具有高性能.高并发.高扩展等特点. openGemini是华为云面向物联网和运 ...
- 实践案例丨CenterNet-Hourglass论文复现
摘要:本案例是CenterNet-Hourglass论文复现的体验案例,此模型是对Objects as Points 中提出的CenterNet进行结果复现. 本文分享自华为云社区<Center ...
- openGemini内核源码正式对外开源
摘要:openGemini是一个开源的分布式时序数据库系统,可广泛应用于物联网.车联网.运维监控.工业互联网等业务场景,具备卓越的读写性能和高效的数据分析能力. 本文分享自华为云社区<华为云面向 ...
- 后CNN探索,如何用RNN进行图像分类
摘要:RNN可以用于描述时间上连续状态的输出,有记忆功能,能处理时间序列的能力,让我惊叹. 本文分享自华为云社区<用RNN进行图像分类--CNN之后的探索>,作者: Yin-Manny. ...
- vue2.x老项目typescript改造过程经验总结
前言: 关于Vue2.x 的TS改造,其实没有啥好说的. 对于vue-cli项目来说,从新跑一遍 vue create xxx-project ,选择Manually select features ...
- 企业如何高效平滑迁移数据?火山引擎DataLeap上线整库搬迁解决方案
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 近日,火山引擎大数据研发治理套件DataLeap上线整库搬迁解决方案,包括整库离线同步.整库实时同步两大能力 ...
- Axure 单键快捷键
如果怕误操作,可以把它关闭
- Java 剑指offer(16) 打印1到最大的n位数
题目 输入数字n,按顺序打印出从1最大的n位十进制数.比如输入3,则打印出1.2.3一直到最大的3位数即999. 思路 陷阱: n过大时是大数问题,不能简单用int或者long数据输出,需要采用字符串 ...
- c#-微软2
练习-编写第一个代码: 在第一次练习中你将使用c#将神圣的程序员用语打印到控制台的标准输出 编写第一行代码: 在软件开发者中,有这么一个传统,那就是将"Hello World!"这 ...
- Go--时间日期相关
1 获取当天零点的时间戳 //当天0点的时间戳 //获取当前时间 t := time.Now() nowTime := time.Date(t.Year(), t.Month(), t.Day(), ...