《JavaScript高级程序设计》读书笔记-在读

摘要

关于《JavaScript高级程序设计》中的事例代码可在附件中查看。html

第二章 <script>元素

defer属性

设置defer="defer",脚本会被延迟到整个页面都解析完毕后在运行,多个延迟脚本并不必定会按照前后顺序执行。前端

async属性

设置async="async",异步加载脚本内容,可是多个异步脚本之间并不必定会按照前后顺序执行。正则表达式

<noscript>元素

该元素能够包含可以出如今<body>中的任何html元素(script除外),只有当浏览器不支持脚本或者支持脚本,可是脚本被禁用时,浏览器才会显示<noscript>中的内容。算法

第三章 基本概念

typeof操做符

typeof是一个操做符,可以返回该数据的数据类型。可是注意其中对于基本类型,除null(返回Object,null被认为是一个空的对象引用)之外,都可以返回正确的结果;对于引用类型,除function(返回Function)之外,一概返回 object 类型。express

Boolean类型

使用Boolean()函数可以将任意类型的一个值转换为Boolean类型值。使用“!!data”可以达到一样的效果,第一个逻辑非操做符是将值转换为布尔值而后取反,第二个逻辑非操做符再次取反获取这个值真正的布尔值。数组

Number类型

JS中将最小值保存在Number.MIN_VALUE中,值为5e-324;将最大值保存在Number.MAX_VALUE中,值为1.7976931348623157e+308。若是某次计算的值超过这个范围,这个值就会自动转换为特殊的Infinity值(Infinity为正无穷,-Infinity为负无穷),使用isFinite()能够判断一个值是否为有穷。浏览器

NaN即非数值,涉及NaN的操做都会返回NaN而且NaN与任何值都不相等,包括NaN自己。isNaN()函数接受一个参数,可以判断这个参数是否“不是数值”。NaN也适用于对象,首先调用对象的valueOf(),而后肯定返回值是否能够转换为数值,若是不能,则基于这个返回值在调用toString(),在测试返回值。bash

Number()、parseInt()、parseFloat()三个函数可以将非数值转换为数值:app

  • Number():将任何数据类型转换为数值。null值转换为0;undefined转换为NaN;空字符串转换为0。
  • parseInt():将字符串转换为数值。空字符串转换为NaN。接受第二个参数设置转换时的进制。
  • parseFloat():将字符串转换为数值,可以解析十进制。

String类型

将一个值转换为String有两种方法。异步

  • 经过toString()方法:每一个值都存在toString()方法,返回相应值的字符串表现(null与undefined没有这个方法)。在调用数值的toString()时,能够传递一个参数,用来指定输出数值的进制基数。
  • 使用转型函数String(),若是值存在toString()方法,返回toString()相应的结果,而null与undefined返回“null”与“undefined”。

一元加操做符

一元加运算符除了用于基本的算术运算,对非数值应用一元加操做符时,可以像Number()转型函数同样对这个值执行转换。

函数

因为ECMAScript函数没有签名,其参数是由包含零或者多个值的数组来表示,而没有函数签名,真正的重载是不可能作到的。

第四章 变量、做用域和内存问题

变量值复制

  • 若是从一个变量向另外一个变量复制基本类型的值,会在变量对象上建立一个新值,而后将该值复制到为新变量分配的位置上,两个变量能够参加任何操做而不会互相影响。
  • 当一个变量向另外一个变量复制引用类型的值时,由于变量中存储的是对象的指针,因此会将指针值复制一份到新变量分配的空间中,所以复制结束后,两个变量实际上将引用同一个对象,改变其中一个变量,会影响另外一个变量。

参数传递

把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另外一个变量同样。基本类型值传递等同基本类型变量复制,引用类型值传递等同引用类型变量复制。

执行环境及做用域

每一个执行环境都有一个与之关联的变量对象,其中定义了环境中的全部变量和函数。
当代码在一个环境中执行的时候,会建立变量对象的一个做用域链。做用域链的用途是保证对执行环境有权访问的全部变量和函数的有序访问。做用域链的前端始终都是当前执行代码所在环境的变量对象。
若是这个环境是函数,则将起活动对象做为变量对象。活动对象最开始的时候只包含arguments对象。

变量声明

使用var声明的变量会自动被添加到最接近的环境中。若是初始化变量时没有使用var声明,该变量会自动添加到全局变量中。

垃圾回收

离开做用域的值将会被自动标记为能够回收,将在垃圾收集期间被删除。
"标记清除"是目前主流的垃圾收集算法,给当前不使用的值加上标记而后回收其内存。
"引用计数"是跟踪记录全部值被引用的次数,可是目前已经不使用这种方式了,由于当存在循环引用的时候,“引用计数”算法就会致使问题。

第五章 引用类型

Object类型

建立Object实例的方式有两种。一种是使用new操做符后面跟Object构造函数;另外一种是使用对象字面量表示法。在经过对象字面量定义对象的时候,实际上不会调用Object构造函数。

Array类型

建立数组的基本方式有两种:

  • 第一种是使用Array构造函数,容许给构造函数传递参数,若是传递的数值就会按照该数值建立指定项数的数组,若是是其余类型的参数,就会建立包含参数的数组;使用Array构造函数时能够省略new操做符。
  • 第二种是使用数组字面量表示法,与对象同样,在使用数组字面量表示法时,不会调用Array构造函数。

数组的length属性不只仅只读,经过设置这个属性,能够从数组的末尾移除项或向数组中添加新项。

数组的sort()排序方法,是先调用每个数组项的toString()方法,而后比较获得的字符串,即便数组项是数值,也是比较的字符串;
sort()方法能够接受一个比较函数做为参数,比较函数设置有两个参数,若是第一个参数应该位于第二个以前,则返回一个负数,以此类推。

Date类型

使用new操做符和Date构造函数可以建立一个基于当前日期和时间的日期对象。使用Date.parse()和Date.UTC()

  • Date.parse()接受一个表示日期的字符串参数,根据这个字符串返回相应日期的毫秒数。若是直接将表示日期的字符串传递给Date构造函数,后台也会调用Date.parse()。
  • Date.UTC()接受的参数分别是年份、基于0的月份(一月是0)、月中的哪一天(1~31)、小时数(0~23)、分钟、秒以及毫秒数,年和月为必须的,其他默认为最小值。将参数直接传递给Date构造函数,会基于本地时区建立时间。
// 两者等同
var now = new Date("May 25, 2004");
var someDate = new Date(Date.parse("May 25, 2004"));

// GMT时间2000年1月1日0时
var gmtTime = new Date(Date.UTC(2000, 0));
// GMT时间2005年5月5日17时55分55秒 
var gmtTime2 = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));

// 本地时间2000年1月1日0时
var localTime = new Date(2000, 0);
// 本地时间2005年5月5日17时55分55秒 
var localTime2 = new Date(2005, 4, 5, 17, 55, 55);
复制代码

Date对toString()和toLocalString()进行了重写,对于valueOf()返回的是日期毫秒表示。

RegExp类型

正则表达式语法

var expression = / pattern/ flag
复制代码

其中模式(pattern)部分能够是任何简单或复杂的正则表达式,每一个正则表达式均可以带有一个或多个标志(flag),正则表达式的匹配模式支持下列3个标志:

  • g:表示全局(global)模式,即模式将被应用于全部字符串,而非在发现第一个匹配项时当即中止;
  • i:表示不区分大小写(case-insensitive)式,即在肯定匹配项时忽略模式与字符串的大小写;
  • m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项。

对于RegExp实例的exec(),若是没有设置全局标志(g),那么在同一个字符串上屡次调用exec()将始终返回第一个匹配项的信息;若是设置了全局标志(g),每次调用exec()会在字符串中继续查找新匹配项。

Regexp的每一个实例都具备下列属性,经过这些属性能够取得有关模式的各类信息。

  • global:布尔值,表示是否设置了g标志。
  • ignorecase:布尔值,表示是否设置了i标志。
  • lastindex:整数,表示开始搜索下一个匹配项的字符位置,从0算起.
  • multiline:布尔值,表示是否设置了m标志。
  • source:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回。

RegExp构造函数包含一些属性,这些属性适用于做用域中全部正则表达式。

  • input 最近一次要匹配的字符串
  • lastMatch 最近一次的匹配项
  • lastParen 最近一次匹配的捕获项
  • leftContext input字符串中lastMatch以前的文本
  • multiline 布尔值,表示是否全部表达式都使用多行模式
  • rightContext input字符串中lastMatch以后的文本
var text = "this has been a short summer";
  var pattern = /(.)hort/g;
      
  /*
   * Note: Opera doesn't support input, lastMatch, lastParen, or multiline. * Internet Explorer doesn't support multiline.
   */        
  if (pattern.test(text)){
      alert(RegExp.input);               //this has been a short summer
      alert(RegExp.leftContext);         //this has been a            
      alert(RegExp.rightContext);        // summer
      alert(RegExp.lastMatch);           //short
      alert(RegExp.lastParen);           //s
      alert(RegExp.multiline);           //false
  }
复制代码

Function类型

函数声明与函数表达式的区别:解析器会率先读取函数声明,并使其在执行任何代码以前可用;而函数表达式则必须等到解析器执行到它所在的代码行才会被解释执行。

// 函数声明
alert(sum(10,10));    //20 执行正常,在代码执行以前,就将函数声明添加到执行环境中了
function sum(num1, num2){
   return num1 + num2;
}  

// 函数表达式
alert(sum(10,10));    //causes an error 尚未执行到函数表达式,sum中尚未保存对函数的引用,程序报错。
var sum = function(num1, num2){
   return num1 + num2;
}; 
复制代码

因为JS中的函数就是对象,所以函数也有属性和方法,每一个函数都包含有两个属性,length和prototype。

  • length:length属性表示函数但愿接受的命名参数的个数。
  • prototype:对于引用类型来说,prototype保存他们全部实例方法的真正所在。换句话说,诸如toString()、valueOf()等方法实际上都保存在prototypr名下,只不过经过各自对象的实例访问罢了。

每一个函数都包含有apply()和call(),这两个方法的用途就是在特定的做用域中调用函数,实际上等于设置函数体内this对象的值。

  • apply()接受两个参数,第一个参数是在其中运行函数的做用域,另外一个是参数数组,能够是数组也能够是arguments对象。
  • call()与apply的做用相同,只是接受参数的方式不同,第一个参数是在其中运行函数的做用域,而其他的参数必须一一传递给函数。
  • bind()会建立一个函数的实例,其中的this值会被绑定到传给bind()函数的值
// apply() demo
function sum(num1, num2){
   return num1 + num2;
}
function callSum1(num1, num2){
   return sum.apply(this, arguments);
}
function callSum2(num1, num2){
   return sum.apply(this, [num1, num2]);
}
alert(callSum1(10,10));   //20
alert(callSum2(10,10));   //20

// call() demo
function sum(num1, num2){
   return num1 + num2;
}
function callSum(num1, num2){
   return sum.call(this, num1, num2);
}
alert(callSum(10,10));   //20

// bind() demo
window.color = "red";
var o = { color: "blue" };                    
function sayColor(){
   alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor();   //blue
复制代码

apply()、call()、bind()这些方法的真正强大之处是可以扩充函数的做用域。

window.color = 'red';
var o = {color:'bluw'};

function sayColor() {
	alert(this.color);
}

sayColor();			// red

sayColor.call(this);	// red
sayColor.call(window);	// red
sayColor.call(o);		// blue
复制代码

使用call()或者apple()、bind()来扩充做用域的最大好处就是对象不须要与方法有任何的耦合关系。 通常来讲咱们须要将sayColor()函数放到对象o中,而后在经过o来调用它,而使用call()函数,咱们就不须要这么作了,对象与方法没有任何的耦合关系。

相关文章
相关标签/搜索