javaScript高程第三版读书笔记
看完《dom编程艺术》现在准备读进阶版的js高程了,由于篇幅较长,所以利用刚看完《dom编程艺术》学到的知识写了段JavaScript代码,来折叠各章的内容。并且应用到了《dom编程艺术》一直强调的“平稳退化”思想,即如果用户的环境不支持JavaScript,内容将不会折叠。够保证观看到内容。
第一章
- DOM1级的目标主要是映射文档的结构
- DOM2级在 原来 DOM的基础上又扩充了鼠标和用户界面事件、范围、遍历,而且通过对象接口增加了对 CSS(Cascading Style Sheets,层叠样式表)的 支持
第二章
- javasCript中的type="text/javascript" 并不是必须写的属性,如果没有指定这个属性,则其默认值仍为 text/javascript
- 浏览器不会检查包含 JavaScript 的文件的扩展名,如果不使用.js 扩展名,请确保服务器能 返回正确的 MIME类型。
- 现代 Web 应用程序一般都把全部 JavaScript引 用放在<body>元素中页面内容的后面,即主要内容后面,</body>标签前面。相对于defer属性,这是最佳选择
- 在XHTML 文档中语法严格,直接影响嵌入的js代码,比如a < b中会发生语法错误,“<” 号应该用相应的 HTML实体(<)代替
- 外部引用js代码的好处是1-可缓存,如果有两个 页面都使用同一个文件,那么这个文件只需下载一次。因此,终结果就是能够加快页面加载的 速度。2-可维护性,也能够在不触及 HTML标记的情况下, 集中精力编辑 JavaScript代码
第三章~基本概念
- 最好都不要使用关键字和保留字作为标识符和属性名, 以便与将来的 ECMAScript版本兼容
- 如果在函数中使用 var 定义一个变量,这是一个局部变量,那么这个变量在函数退出后就会被销毁。例如
function test(){
var message = "hi"; // 局部变量
}
test();
alert(message); // 错误! - 在函数中省略var 定义一个变量,这个变量会是全局变量,但并不推荐这么做,而且给未经声明的变量赋值在严格模式 下会导致抛出 ReferenceError 错误。
- ECMAScript中有 5种简单数据类型(也称为基本数据类型):Undefined、Null、Boolean、Number 和String。还有1种复杂数据类型——Object,Object 本质上是由一组无序的名值对组成的
- 鉴于 ECMAScript 是松散类型的,因此需要有一种手段来检测给定变量的数据类型——typeof
"undefined"——如果这个值未定义;
"boolean"——如果这个值是布尔值;
"string"——如果这个值是字符串;
"number"——如果这个值是数值;
"object"——如果这个值是对象或 null;
"function"——如果这个值是函数。 - Undefined 类型只有一个值,即特殊的 undefined。在使用 var 声明变量但未对其加以初始化时, 这个变量的值就是 undefined
- null是第二个只有1个值的数据类型,这个特殊的值是null,从逻辑角度上说,null是一个空对象指针,而这也正是使用typeof 操作符检测 null 值时会返回"object"的原因
- 如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为 null 而不是其他值。这样 一来,只要直接检查 null 值就可以知道相应的变量是否已经保存了一个对象的引用
- 各种数据类型的值都能通过调用转换函数Boolean()转换成布尔值,具体可以看这篇→转型函数 Boolean() 文章。知道这些后,能帮助对理解流控制语句(如 if 语句)有很大帮助。
八进制字面值的第一位必须是零(0),然后是八进制数字序列(0~7),无效的八进制会被当做十进制解析,严格模式下不支持八进制
- 在进行算术计算时,所有以八进制和十六进制表示的数值终都将被转换成十进制数值。 所以不要用十进制之外的数组进行算术运算。
- 浮点数值的高精度是 17位小数,但精确度不高,有些特定的数字会出问题,例如0.1和0.2的和并不是0.3,是 0.30000000000000004。并不是所以数组都是这样,例如0.5和0.25的值不会出现问题。这是使用基于 IEEE754 数值的浮点计算的通病,并非js一家,其他使用相同数值格 式的语言也存在这个问题
- 如果某次计算的 结果得到了一个超出 JavaScript数值范围的值,那么这个数值将被自动转换成特殊的 Infinity 值。这个值不能再参与计算,可以用isFinite()函数查看一个数是不是有穷的(换句话说,是不是位于 小和大的数值之间)。是返回true,否返回false。不过一般不会超出的。一般最小值是5e-324,最大值是1.7976931348623157e+308。
- NaN,即非数值(Not a Number)是一个特殊的数值,,这个数值用于表示一个本来要返回数值的操作数 未返回数值的情况。其他语言0做除数会报错并停止执行代码,而js则会返回NaN,这样就不会抛出错误了
- isNaN()函数能帮助我们确定参数是否“不是数值”。任何不能被转换为数值的值都会导致这个函数返回 true。(这有点绕)。例如isNaN(10)会返回false;而isNaN("blue") 会返回 true。因为字符串blue不能被转换成数值。
- 在 ECMAScript 5 JavaScript引擎中,parseInt()已经不具有解析八进制值的能力,即使是在非严格模式下
基数意味着让 parseInt()决定如何解析输入的字符串,因此为了避免错误的解析,我们建 议无论在什么情况下都明确指定基数。
于 parseFloat()只解析十进制值,而且如果解析的值可以解析成一个整数,则会返回整数。
- 前置型如++i 会先加再计算,和后置型i++会先运算再加。
- ECMAScript函数不介意传递进 来多少个参数,也不在乎传进来参数是什么数据类型 。ECMAScript中的参数在内部是用一个数组来表示的。函数体内可以通过 arguments 对象来 访问这个参数数组,还可以用arguments.length查看参数个数
- ECMAScript没有重载,但通过检查传入函数中参数的类型和数量并作出不同的反应可以模仿重载的方法。
第四章~变量、作用域和内存问题
- ECMAScript 变量可能包含两种不同数据类型的值:基本类型值(也就是普通变量)和引用类型值(对象)。
- 把一个变量赋值给另外一个变量,这两个变量的内存地址是相互独立的。
- 当从一个变量向另一个变量复制引用类型的值时,这个变量是一个指针副本,指向这个对象的属性。他们之间是关联的,相互影响的。
- 全局执行环境直到应用程序退 出——例如关闭网页或浏览器——时才会被销毁
- 每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。 而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。ECMAScript 程序中的执行流 正是由这个方便的机制控制着。
- 如果在for循环中使用var来创建变量,比如
这个i在for循环结束后仍然存在于其外部环境中。最近的ECMASript可以设置用let来设置块级变量,不过只有IE11才支持块级作用域
变量查询也不是没有代价的。很明显,访问局部变量要比访问全局变量更快,因 为不用向上搜索作用域链。JavaScript 引擎在优化标识符查询方面做得不错,因此这 个差别在将来恐怕就可以忽略不计了。
- JavaScript 具有自动垃圾收集机制,最常用的垃圾收集方式是标记清除,当变量离开环境时,则将其 标记为“离开环境,最后,垃圾收集器 完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。该回收机制的另一个缺点是标记过程必须遍历所有的内存来找到垃圾。对于没有多少垃圾的系统来说,这个不是问题,但是如果的函数式编程方式会产生大量的垃圾。这种算法的思想是给当前不使用的值加上标记,然 后再回收其内存
- 另一种不太常见的垃圾收集策略叫做引用计数(reference counting)。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1。 如果同一个值又被赋给另一个变量,则该值的引用次数加 1。当垃圾收集器下次再运行时,它就会释放那 些引用次数为零的值所占用的内存。但这个方法在指针相互引用(也就是环形引用)方面有严重问题,已被弃用
- 在IE8及以下的浏览器中,有一部分对象并不是原生 JavaScript 对象。例如,其 BOM 和 DOM 中的对象就是 使用 C++以 COM(Component Object Model,组件对象模型)对象的形式实现的,而 COM对象的垃圾 收集机制采用的就是引用计数策略。。换句话说,只要在 IE8及以下中涉及 COM对象,就会 存在循环引用的问题。,这种循环引用会导致这两个变量的内存永远不会被回收,需要这样来消除循环。(IE8的解决方法)
由于给浏览器分配的内存比桌面软件少,所以要注意优化你的代码,优化内存占用的最佳方式,就是为执行 中的代码只保存必要的数据。一旦数据不再有用,最好通过将其值设置为 null 来释放其引用——这个 做法叫做解除引用(dereferencing)。例如下面的例子
在这个例子中,变量 globalPerson 取得了 createPerson()函数返回的值。在 createPerson() 函数内部,我们创建了一个对象并将其赋给局部变量 localPerson,然后又为该对象添加了一个名为 name 的属性。最后,当调用这个函数时,localPerson 以函数值的形式返回并赋给全局变量 globalPerson。由于 localPerson 在 createPerson()函数执行完毕后就离开了其执行环境,因此 无需我们显式地去为它解除引用。但是对于全局变量 globalPerson 而言,则需要我们在不使用它的时候手工为它解除引用,这也正是上面例子中最后一行代码的目的。 不过,解除一个值的引用并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离 执行环境,以便垃圾收集器下次运行时将其回收。- 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中;
- 引用类型的值是对象,保存在堆内存中
- 包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针;
- 确定一个值是哪种基本类型可以使用 typeof 操作符,而确定一个值是哪种引用类型可以使用 instanceof 操作符。
- 执行环境有全局执行环境(也称为全局环境)和函数执行环境之分;
- 每次进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链;
- 函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全 局环境;
- 全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据;
第五章~引用类型
- 在通过对象字面量定义对象时,实际上不会调用 Object 构造函数(Firefox 2及 更早版本会调用 Object 构造函数;但 Firefox 3之后就不会了)
- 对象字面量语法,函数名也可以用字符串。
- 对象的引用包含2种方法,Object.name或者Object.["name"]
数组多可以包含 4 294 967 295个项,这几乎已经能够满足任何编程需求了。如 果想添加的项数超过这个上限值,就会发生异常。而创建一个初始大小与这个上限值 接近的数组,则可能会导致运行时间超长的脚本错误。
- value instanceof Array(ES3版的)和Array.isArray(value) [ES5版的]都可以确定一个一个值到底是不是数组,前面的在多框架上是有问你的,ES5版本的比较好,但IE9及以上才支持
- pop()方法会删除数组最后的一个值,并返回删除的那个值,
- 栈是一种 LIFO(Last-In-First-Out, 后进先出)的数据结构,也就是新添加的项早被移除。而栈中项的插入(叫做推入)和移除(叫做 弹出),只发生在一个位置——栈的顶部。ECMAScript为数组专门提供了 push()和 pop()方法,以便 实现类似栈的行为。
- 用sort()来排序数组,会首先对数组调用toStrinf()方法将数组列成字符串来进行对比,但这样就会导致数字变成列出来之后就变成字符串,这就需要编写一个函数,然后在sort(compare)中调用,即可达到排序的目的
concat()数组拼接
- new Date(Date.parse("may,25,2017,12:05:00"));可以设置指定的日期,,如果直接将表 示日期的字符串传递给 Date 构造函数,也会在后台调用 Date.parse()。也就是说new Date("may,25,2017,12:05:00");也是等价的,
- arguments 的主要用途是保存函数参数, 但这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。 具体请查看这篇文章→arguments.callee
- 一定要牢记,函数的名字仅仅是一个包含指针的变量而已。因此,即使是 在不同的环境中执行,全局的 sayColor()函数与 o.sayColor()指向的仍然是同一 个函数。
- call()方法与 apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于 call() 方法而言,第一个参数是 this 值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用 call()方法时,传递给函数的参数必须逐个列举出来
- var b1 = new Boolean(true);b1返回的typeof是object。而var b2 = false;返回的是boolean
- 建议永远不要使 用 Boolean 对象。
- toFixed()方法会按照指定的小数位返回数值的字符串表示,例如:
- ECMAScript 5为所有字符串定义了 trim()方法。这个方法会创建一个字符串的副本,删除前置及 后缀的所有空格。
- Object 是一个基础类型,其他所有类型都从 Object 继承了基本的行为;
第六章~面向对象编程
- [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特 性,或者能否把属性修改为访问器属性。像前面例子中那样直接在对象上定义的属性,它们的 这个特性默认值为 true。
- [[Enumerable]]:表示能否通过 for-in 循环返回属性。像前面例子中那样直接在对象上定 义的属性,它们的这个特性默认值为 true。
- [[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候, 把新值保存在这个位置。这个特性的默认值为 undefined。
- 要修改属性默认的特性,必须使用 ECMAScript 5的 Object.defineProperty()方法。这个方法 接收三个参数:属性所在的对象、属性的名字和一个描述符对象。其中,描述符(descriptor)对象的属 性必须是:configurable、enumerable、writable 和 value。设置其中的一或多个值,可以修改 对应的特性值
- 使用 ECMAScript 5的 Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述 符
- 使用 Object.getPrototypeOf() 可以方便地取得一个对象的原型
- 每当代码读取某个对象的某个属性时,会现在实例本身寻找给定名字的属性,找到就返回数据,不会必再搜索原型对象的属性,等于屏蔽了原型对象的属性。找不到才会去搜索原型对象的属性。
- 可以通过delete 删除实例对象的属性,重新返回原型对象属性。原型对象属性不可被删除
- hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中。)只在给定属性存在于对象实例中时,才会返回 true
- 要取得对象上所有可枚举的实例属性,可以使用 ECMAScript 5的 Object.keys()方法IE9+
- 如果你想要得到所有实例属性,无论它是否可枚举,都可以使用 Object.getOwnPropertyNames() IE9+
- 组合使用构造函数模式和原型模式
创建自定义类型的常见方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实 例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本, 但同时又共享着对方法的引用,大限度地节省了内存。另外,这种混成模式还支持向构造函数传递参 数;可谓是集两种模式之长。下面代码例子。在这个例子中,实例属性都是在构造函数中定义的,而由所有实例共享的属性 constructor 和方 法 sayName()则是在原型中定义的。而修改了 person1.friends(向其中添加一个新字符串),并不 会影响到 person2.friends,因为它们分别引用了不同的数组。 这种构造函数与原型混成的模式,是目前在 ECMAScript中使用广泛、认同度高的一种创建自 定义类型的方法。可以说,这是用来定义引用类型的一种默认模式。
- 用动态原型模式时,不能使用对象字面量重写原型。如果 在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。
- 通过原型链实现继承时,不能使用对象字面量创建原型方法。因为这 样做就会重写原型链
- 把 configurable 特性设置为 false 之后就会有限制,包括示不能从对象中删除属性,一旦把属性定义为不可配置的, 就不能再把它变回可配置,修改除 writable 之外 的特性,都会导致错误:
- 在调用 Object.defineProperty()方法时,如果不指定,configurable、enumerable 和 writable 特性的默认值都是 false
- 按照惯例,构造函数始终都应该以一个 大写字母开头,而非构造函数则应该以一个小写字母开头。这个做法借鉴自其他 OO语言
- 每当代码读取某个对象的某个属性时,会先搜索实例本身,如果没有找到才会去搜索原型对象
- 虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。
- 单独使用时,in 操作符会在通 过对象能够访问给定属性时返回 true,无论该属性存在于实例中还是原型中。看一看下面的例子。
- 在使用 for-in 循环时,返回的是所有能够通过对象访问的属性,其中既包括实例中的,也包括原型中的属性。如果屏蔽了原型对象(即将 [[Enumerable]]标记为 false 的属性),也会返回实例的属性
- 原型链:子类的原型指向父类的实例从而实现原型共享。
第七章~函数表达式
- 在执行 代码之前会先读取函数声明。这就意味着可以把函数声明放在调用它的语句后面。 例子不会抛出错误,因为在代码执行之前会先读取函数声明。
- 创建一个函数并将它赋值给变量 functionName。 这种情况下创建的函数叫做匿名函数
- ,在编写递归函数时,使用 arguments.callee 总比使用函数名更保险,但在严格模式下,不能通过脚本访问 arguments.callee,访问这个属性会导致错误。不过,可 以使用命名函数表达式来达成相同的结果。
- 闭包是指有权访问另一个 函数作用域中的变量的函数。
- ,当 createComparisonFunction()函数返回后,其执行环境的作用域链会被销毁,但它的活 动对象仍然会留在内存中;直到匿名函数被销毁后,createComparisonFunction()的活动对象才会 被销毁
- 由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过 度使用闭包可能会导致内存占用过多,我们建议读者只在绝对必要时再考虑使用闭 包。虽然像 V8 等优化后的 JavaScript 引擎会尝试回收被闭包占用的内存,但请大家 还是要慎重使用闭包。
- 递归函数应该始终使用 arguments.callee 来递归地调用自身,不要使用函数名——函数名可 能会发生变化。
- 在后台执行环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域
- 使用闭包可以在 JavaScript中模仿块级作用域(JavaScript本身没有块级作用域的概念),要点如下。 、
- 创建并立即调用一个函数,这样既可以执行其中的代码,又不会在内存中留下对该函数的引用
- 结果就是函数内部的所有变量都会被立即销毁——除非将某些变量赋值给了包含作用域(即外 部作用域)中的变量
- 闭包还可以用于在对象中创建私有变量,相关概念和要点如下。
- 即使 JavaScript中没有正式的私有对象属性的概念,但可以使用闭包来实现公有方法,而通过公 有方法可以访问在包含作用域中定义的变量。
- 有权访问私有变量的公有方法叫做特权方法。
- 可以使用构造函数模式、原型模式来实现自定义类型的特权方法,也可以使用模块模式、增强 的模块模式来实现单例的特权方法
- JavaScript 中的函数表达式和闭包都是极其有用的特性,利用它们可以实现很多功能。不过,因为 创建闭包必须维护额外的作用域,所以过度使用它们可能会占用大量内存。
第八章~BOM
- 所有在全局作用域中声明 的变量、函数都会变成 window 对象的属性和方法。
- 全局变量不能通过 delete 操作符删除,而直接在 window 对象上的定义的属性可以。 例如:
//
//
javaScript高程第三版读书笔记的更多相关文章
- Linux设备驱动程序 第三版 读书笔记(一)
Linux设备驱动程序 第三版 读书笔记(一) Bob Zhang 2017.08.25 编写基本的Hello World模块 #include <linux/init.h> #inclu ...
- JavaScript高级程序设计第三版-读书笔记(1-3章)
这是我第一次用markdown,也是我第一次在网上记录我自己的学习过程. 第一章 JavaScript主要由以下三个不同的部分构成 ECMAScript 提供核心语言功能 DOM 提供访问 ...
- effective java(第三版)---读书笔记
第一章 引言 < Effective Java>这本书并不厚,而且并不适合初学者,适合有一定的工作经验的java攻城狮.这本书不是百科全书式的JAVA 手册,而是试图在讲述如何正确.高效地 ...
- JavaScript高程第三版笔记-面向对象编程
之前有篇博客曾提到过一点js的面向对象编程:js面向对象编程. 这里就结合js高程详细剖析一下javascript的面向对象编程. 前序: 1⃣️Object.defineProperty() var ...
- JavaScript高程第三版笔记(1-5章)
第2章:在html中使用javascript ①script标签的defer属性 <script type="text/javascript" defer="def ...
- JavaScript高程第三版笔记-DOM扩展
在那个刀耕火种的年代,用过jQuery的都体会到了jQuery带来的便捷,尤其是元素选择器. jQuery(www.jquery.com)的核心就是通过 CSS 选择符查询 DOM 文档取得元素的引用 ...
- JavaScript高程第三版笔记-函数表达式
1⃣️递归 阶乘函数: function factorial(num){ ){ ; } ); } } 改装一:(arguments.callee指向正在执行的函数的指针,实现解耦) function ...
- 《ECMAScript6标准入门》第三版--读书笔记
2015年6月,ECMAScript 6正式通过,成为国际标准.尽管在目前的工作中还没有使用ES6,但是每项新技术出来总是忍不住想尝尝鲜,想知道ES6能为前端开发带来哪些变化?对自己的工作有哪些方面可 ...
- CSS权威指南-第三版--读书笔记
第一章:CSS和文档 html是结构化语言,css是样式语言,html主要用来被强大的搜索引擎更好的索引,更好的让一个盲人通过语音浏览器来了解我们的网页,这也就是为什么说html是结构话语言,因为这是 ...
随机推荐
- LINUX怎么修改IP地址
1,先搜索了一下,得到以下解释 IP IP地址 Netmark 子网掩码 Gateway 默认网关 HostName 主机名称 DomainName 域名 DNS DNS的IP 2,需要修改的文件常有 ...
- 实战weblogic集群之应用部署
一.创建应用发布目录,上传应用包. 1.在10.70.52.11-14的/app/sinova目录下建立applications目录(名称可以自定义),作为我们应用的发布目录. $ mkdir /ap ...
- 【动态规划】Vijos P1218 数字游戏(NOIP2003普及组)
题目链接: https://vijos.org/p/1218 题目大意: 一个N个数的环,分成M块,块内的数求和%10,最后每块地值累乘,求最大和最小. n(1≤n≤50)和m(1≤m≤9)太小了可以 ...
- call, apply && bind, currying
简要概括: apply(): 将函数作为指定对象的方法来调用,传递给它的是指定的参数数组 ——function.apply(thisobj, args) 或者 function.apply(thiso ...
- 原生JavaScript拖动div兼容多种浏览器
说句题外话,虽然博客园嵌入式氛围不行,Web前端氛围还是很好的.我又从 chinaunix 回来了. <html> <head> <script type="t ...
- HDU 1203 I NEED A OFFER! 01背包
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1203 解题思路:简单的01背包,用dp[i]表示花费不超过i时的最大可能性 状态转移方程 dp[i]= ...
- Intellij 快捷键大全
Intellij IDEA的快捷键非常好用,能大大提高我们的开发速度.这里列举了一些常用的快捷键. 快速查找: Ctrl+N 查找类 Ctrl+R 替换当前窗口的文本 Ctrl+F 当前代码中查 ...
- javascript 函数 方法
函数 1.函数的定义 (1)function 函数名(x){ 函数执行体; } (2)var 函数名=function(x){ 函数执行体; }; 这种方法说明,在javascript中,函数就是一种 ...
- jeety and tomcat plugins In Maven
(转自)maven jetty 插件使用 本机环境 JDK 7 Maven 3.2 Jetty 9.2 Eclipse Luna pom.xml 配置 在你的 pom.xml 文件中添加 jetty ...
- mysql 循环插入100w
use md5db; DROP PROCEDURE if exists myFunction; delimiter $$ CREATE PROCEDURE myFunction() BEGIN DEC ...