JavaScript高级程序设计 精读4-5章

4.1 基本类型和引用类型的值

基本类型值:简单的数据段

引用类型值:那些可能由多个值构成的对象

基本数据类型:Undefined Null Boolean Number String 这五种基本数据类型是按值访问的,因为可以操作保存在变量的值

引用类型的值:保存在内存中的对象。引用类型的值是按引用访问的。

js不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。

  • 4.1.1 动态的属性

    定义基本类型值和引用类型值的方式:创建一个变量并为该变量赋值。
    对于引用类型的值,我们可以为其添加属性和方法,也可以改变和删除其属性和方法。

复制变量值

基本类型值:如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。

引用类型值:当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到
为新变量分配的空间中。 这个值的副本实际是一个指针,而这个指针指向存储在堆中的一个对象。

  • 4.1.3 传递参数

ECMA中所有函数的参数都是按值传递的。 把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。

  • 4.1.4 检测类型

typeof ==> 字符串 数值 布尔类型 undefined(检测基本数据类型)

typeof 一个对象或null 返回的都是object

instanceof

语法: result= variable instanceof constructor

变量是给定的引用类型的实例,那么instanceof操作符就会返回true。

所有引用类型的值都是Object的实例。

4.2 执行环境及作用域

执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。

全局执行环境是最外围的一个执行环境。

当代码在一个环境中执行时,会创建变量对象的一个作用域链。

​ 作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。

​ 作用域的前端,始终都是当前执行的代码所在环境的变量对象。

如果这个环境是函数,则将其活动对象作为变量对象。活动对象在最开始时只包含一个变量,即arguments对象。

​ 全局执行环境的变量对象始终都是作用域链中的最后一个对象。

​ 标识符解析是沿着作用域一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直至找到标识符为止。

​ 内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。

​ 每个函数都可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。

  • 4.2.1延长作用域链
  • 4.2.2 没有块级作用域

在js中,if语句中的变量声明会将变量添加到当前的执行环境(在这里是全局环境)中。在使用for语句时尤其要牢记这一差异。

——声明变量

​ 使用var声明的变量会自动被添加到最接近的环境中。在函数内部,最接近的环境就是函数的局部环境;在with语句中,最接近的环境是函数环境。如果初始化变量时没有使用var声明,该变量会自动被添加到全局环境。

——查询标识符

​ 访问局部变量要比访问全局变量更快,因为不用向上搜索作用域链。

4.3 垃圾收集

JS具有自动垃圾收集机制(找出那些不再继续使用的变量,然后释放其占用的内存)

执行环境会负责管理代码执行过程中使用的内存。

函数中局部变量的正常生命周期:局部变量只在函数执行的过程中存在。而在这个过程中,会为局部变量在栈(或堆)内存上分配相应的空间,以便存储它们的值。

  • 4.3.1 标记清除

JS中最常用的垃圾收集方式是标记清除。

当变量进入环境时,就将这个变量标记为“进入环境”。

从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则标记为“离开环境”

  • 4.3.2 引用计数

引用计数的含义是跟踪记录每个值被引用的次数。

循环引用:对象A中包含一个指向对象B的指针,而对象B中也包含一个指向对象A的引用。

  • 4.3.3 性能问题
  • 4.3.4 管理内存

解除引用:一旦数据不再有用,最好通过将其设置为null来释放其引用

第五章 引用类型

引用类型的值时引用类型的一个实例。引用类型是一种数据结构,用于将数据和功能组织在一起。

引用类型有时候也被称为对象定义,因为他们描述的是一类对象所具有的属性和方法。

5.1 Object类型

大多数引用类型的值都是Object类型的实例。

  • 创建Object实例有两种
  1. 使用new操作符后跟Object构造函数

    var person = new Object();
    person.name="";
    
  2. 使用对象字面量表示法

    var person = {
      name:"nihao";
      age:29
    };
    
  • 访问对象属性用的都是点表示法

5.2 Array类型

  • ECMAScript数组的每一项可以保存任何数据的类型。
  • ECMAScript数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据
  • 创建数组的基本方式

1.使用Array构造函数

var colors = new Array();

2.使用数组字面量表示法。

数组字面量由一对包含数组项的方括号表示。(数组字面量由一对包含数组项的方括号表示,多个数组项之间以逗号隔开)

数组的length属性,不是只读。通过设置这个属性,可以从数组的末尾移除项或向数组中添加新项。

  • 5.2.1 检测数组

1.对于一个网页,或者一个全局作用域而言 ,使用instanceof操作符就能得到满意的结果。

(instanceof 它假定只有一个全局执行环境)。

2.Array.isArray()目的:最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建。

if(Array.isArray(value)){
  
}
  • 5.2.2 转换方法

所有对象到具有toLocaleString()、toSting()、valueOf()方法

1.调用数组的toString()方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。

2.valueOf()返回的还是数组。

3.如果不给join方法传入任何值,或者给它传入undefined,则使用逗号作为分隔符。

  • 5.2.3 栈方法

1.栈:LIFO (Last—In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除。 而栈中项的插入和移除,只发生在一个位置——栈的顶部

2.push() :可以接受任意数量的参数,把它们逐个添加到数组末尾,并返回修改后的数组的长度。

3.pop()方法则从数组末尾移除最后一项,减少数组的length值,然后返回移除的项。

  • 5.2.4 队列方法

队列:FIFO(First-In-First-Out,先进先出)。队列在列表的末端添加项,从列表的前端移除项。

1.shift(),它能够移除数组中的第一个项并返回该项,同时将数组长度减1.

2.unshift():能在数组前端添加任意个项并返回新数组的长度。因此,同时使用unshift()和pop()方法,可以从相反的方向来模拟队列,即在数组的前端增加项,从数组末端移除项。

  • 5.2.5重排序方法

1.reverse()方法会反转数组项的顺序

2.sort()方法按升序排列数组项。为了实现排序,sort()方法会调用每个数组项的toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值,sort()方法比较的也是字符串。

sort()方法可以接受一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。

?比较函数

比较函数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等则返回0,如果第一个参数应该位于第二个之后则返回一个正数。

  • 5.2.6 操作方法

1.concat()方法可以基于当前数组中所有项创建一个新数组。

具体说:这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。

2.slice():它能够基于当前数组中的一或多个项创建一个新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。

一个参数的情况下:slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。

两个参数:该方法返回起始和结束位置之间的项——但不包括结束位置的项

(slice()方法不会影响原始数组)

slice()方法的参数中有一个负数,则用数组长度加上该数来确定相应的位置

3.splice()方法

删除:可以删除任意数量的项,只需指定2个参数:要删除的第一项的位置和要删除的项数。

例如:splice(0,2)会删除数组中的前两项。

插入:可以向指定位置插入任意数量的项,只需提供三个参数:起始位置,0(要删除的项数)和要插入的项

例如:splice(2,0,“red”,“green”)会从当前数组的位置2开始插入字符串“red” “green”

替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项:只需指定三个参数:起始位置 要删除的项数和要插入的任意数量的项。

例如:splice(2,1,“red”,“green”)会删除当前数组位置2的项,然后再从位置2开始插入字符串

slice()方法始终都会返回一个数组,该数组包含从原始数组中删除的项(如果没有删除任何项,则返回一个空数组)

  • 5.2.7 位置方法

位置方法:indexOf()和 lastIndexOf()。这两个方法都接受两个参数:要查找的项和表示查找起点位置的索引。

indexOf()方法从数组的开头开始向后查找

lastIndexOf()方法则从数组的末尾开始向前查找

这两种方法都返回要查找的项在数组的位置,或者在没找到的情况下返回-1.

(在比较第一个参数与数组的每一项的时候,会使用全等操作符)

  • 5.2.8 迭代方法

5个方法:每个方法都接收两个参数:要在每一项上运行的函数和运行该函数的作用域的对象——影响this值。传入这些方法中的函数会接收三个参数:数组项的值,该项在数组的位置和数组对象本身。

1.every():对数组的每一项运行给定函数,如果该函数对每一项都返回true,则返回true

2.filter():对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组

3.forEach():对数组中的每一项运行给定函数。这个方法没有返回值

4.map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组

5.some():对数组中的每一项运行给定函数,如果该函数对任意一项返回true,则返回true。

以上方法都不会修改数组中的包含的值。

  • 5.2.9 归并方法

两个归并数组的方法:reduce()和reduceRight()。这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。

reduce()方法:从数组的第一项开始,逐个遍历到最后。

reduceRight():从数组的最后一项开始,向前遍历到第一项

接收的参数:一个在每一项调用的函数和作为归并基础的初始值。

传给reduce()和reduceRight()的函数接收4个参数:前一个值,当前值,项的索引和数组对象。

这个函数返回的任何值都会作为第一个参数自动传给下一项。

5.3 Date类型

创建一个日期对象:

var now = new Date()

1.Date.parse ()方法:接收一个表示日期的字符串参数,然后尝试根据这个字符串返回相应日期的毫秒数。

2.Date.UTC()方法:也返回日期的毫秒数,但它与Date.parse()在构建时使用不同的信息。

Date.UTC的参数分别是年份,基于0的月份(一月是0),月中的哪一天(1-31),小时数(0-23),分钟,秒,毫秒。

3.Date.now()方法:返回调用这个方法时的日期和时间的毫秒数

var start = Date.now();
doSomething();
var stop= Data.now(),
    result = stop - start;

+操作符也可以获取Date对象的时间戳,也可以达到同样的目的。

  • 5.3.1 继承的方法

Date类型的tolocaleString ()方法会按照与浏览器的地区相适应的格式返回日期和时间。

toString()方法通常返回带有时区信息的日期和时间

valueOf()方法,根本不返回字符串,而是返回日期的毫秒表示。

  • 5.3.2 日期格式化方法
  • 5.3.3 日期/时间组件方法

5.4 RegEXp类型

通过RegExp类型来支持正则表达式

var expression = /pattern/flags;

其中的模式(pattern)部分可以是任何简单或复杂的正则表达式,可以包含字符类,限定符,分组,向前查找以及反向引用。

1.g:表示全局模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止

2.i:表示不区分大小写模式,即在确定匹配项时忽略模式与字符串大小写

3.m:表示多行模式。即在到达一行文本末尾时,还会继续查找下一行中是否存在与模式匹配的项。

正则表示式中的元字符包括:( [ { \ ^ $ | ) ? * + .]}

创建正则表达式:

1.字面量形式来定义

正则表达式字面量始终共享同一个RegExp实例

2.使用RegExp构造函数

接收两个参数:一个是要匹配的字符串模式,另一个是可选的标志字符串。

构造函数创建的每一个新的RegExp实例都是一个新实例

  • 5.4.1 RegExp实例属性

RegExp的每个实例都具有下列属性,通过这些属性可以取得有关模式的各种信息。

1.global:布尔值,表示是否设置了g标志

2.ignoreCase:布尔值,表示是否设置了i标志

3.lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从0算起

4.multiline:布尔值,表示是否设置了m标志

5.sourse:正则表示式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回。

source属性保存的是规范形式的字符串,即字面量形式所用的字符串

  • 5.4.2 RegExp实例方法

RegExp 对象的主要方法是 exec(),该方法是专门为捕获组而设计的

1.exec():接收一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组;或者没有匹配项的情况下返回null。

index、input

2.test():接受一个字符串参数。在模式与该参数匹配的情况下返回true,否则返回false。

RegExp 实例继承的 toLocaleString()和 toString()方法都会返回正则表达式的字面量,与创
建正则表达式的方式无关

  • 5.4.3 RegExp构造函数属性

这些属性适用于作用域中的所有正则表达式,并且基于所执行的最近一次正则表达式操作而变化。

  • 5.4.4 模式的局限性

5.5 Function 类型

函数实际上是对象,函数名实际上是一个指向函数对象的指针,不会与某个函数绑定。函数通常是使用函数声明语法定义的。

每一个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。

定义函数的方法

1.使用函数声明语法定义

function sum(num1,num2){
   return num1 + num2;
}

2.函数表达式定义函数

var sum = function(num1,num2){
  return num1 + num2;
};

3.使用Function构造函数

var sum = new Function("num1","num2","return num1 + num2");//不推荐 

Function构造函数可以接收任意数量的参数,但最后一个函数始终都被看成是函数体,而前面的参数则枚举出了新函数的参数。

”函数是对象,函数名是指针“

由于函数名仅仅是指向函数的指针,因此函数名与包含 对象指针的其他变量没有什么不同。(函数可能会有多个名字)

  • 5.5.1 没有重载
  • 5.5.2 函数声明与函数表达式

函数声明 /函数表达式

解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问);至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。

  • 5.5.3 作为值的函数

函数名本身就是变量,所以函数也可以作为值来使用。

  • 5.5.4 函数内部属性

在函数内部,有两个特殊的对象:arguments和this。

1.arguments:类数组对象,包含着传入函数的所有参数。

属性:callee 该属性是一个指针,指向拥有这个arguments对象的函数。(消除耦合)

2.this

this引用的是函数执行的环境对象。

3.caller:保存着调用当前函数的函数引用,如果是在全局作用域中调用当前函数,它的值为null。

不能为函数的caller属性赋值。

  • 5.5.5 函数属性和方法

函数是对象

函数也有属性和方法。

每个函数都包含两个属性:length和prototype。

1.length属性表示函数希望接收的命名参数的个数

2.prototype属性:

对于引用类型而言,prototype是保存它们所有实例方法的真正所在。

每个函数都包含两个非继承而来的方法:apply()和call ()

用途:在特定的作用域中调用函数,实际上等于设置函数体内this对象的值

1.apply()方法:接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组(Array实例/arguments对象)。

打算直接传入 arguments 对象,或者包含函数中先接收到的也是一个数组,那么使用 apply()
肯定更方便;否则,选择 call()可能更合适.

使用 call()(或 apply())来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。

2.bind():创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

5.6 基本包装类型

后台处理:

(1) 创建 String 类型的一个实例;
(2) 在实例上调用指定的方法;
(3) 销毁这个实例。
可以将以上三个步骤想象成是执行了下列 ECMAScript 代码。

var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;

引用类型与基本包装类型的主要区别就是对象的生存期。

  • 5.6.1 Boolean类型

永远不要使用Boolean对象

布尔表达式中的所有对象都会被转换为 true

  • 5.6.2 Number 类型

toFixed()方法会按照指定的小数位返回数值的字符串表示。

toExponential()方法 格式化数值 该方法返回以指数表示法表示的数值的字符串形式。

toPrecision()方法可能会返回固定大小(fixed)格式,也可能返回指数 (exponential)格式这个方法接收一个参数,即表示数值的所有数字的 位数(不包括指数部分)。

  • 5.6.3 String类型

1.字符方法

都接收一个参数,即基于0的字符位置。

chartAt():以单字符字符串的形式返回给定位置的那个字符

chartCodeAt():得到的是字符编码

2.字符串操作方法

concat():用于将一或多个字符串拼接起来,返回拼接得到的新字符串

slice()、substr()和 substring():返回被操作字符串的一个子字符串,而且也都接受一或两个参数。第一个参数指定子字
符串的开始位置,第二个参数(在指定的情况下)表示子字符串到哪里结束

slice()和 substring()的第二个参数指定的是子字符串最后一个字符后面的位置。而 substr()的第二个参数指 定的则是返回的字符个数。

  1. 字符串位置方法

indexOf()

lastIndexOf()

4.trim()方法

trim():创建一个字符串的副本,删除前置及后缀的所有空格,然后返回结果

5.字符串大小转换方法

toLowerCase()

toLocaleLowerCase()

toUpperCase()

toLocaleUpperCase()

6.字符串的模式匹配方法

match():只接收一个参数,要么是一个正则表达式,要么是一个RegExp对象。(本质与调用exec()方法 一样)

search():由字符串或 RegExp 对象指定的一个正则表达式

replace():接受两个参数,一个参数可以是一个 RegExp 对象或者一个字符串(这个字符串不会被转换成正则表达式),第二个参数可以是一个字符串或者一个函数

split():基于指定的分隔符将一个字符串分割成多个子字符串,并将结果放在一个数组中。可以接受可选的第二个参数,用于指定数组的大小,以便确保返回的数组不会超过既定大小

  1. localCompare()方法

8.fromChartCode方法

接收一或多个字符编码,然后将它们转换成一个字符串

9.HTML方法

5.7 单体内置对象

内置对象: ECMAScript 实现提供的、不依赖于宿主环境的对象,这些对象在 ECMAScript 程序执行之前就已经存在

  • 5.7.1 Global对象

不属于任何其他对象的属性和方法,最终都是它的属性和方法。

对象的方法:isNaN()、isFinite()、parseInt()、parseFloat()、URI编码方法

1.URI方法

encodeURI():不会对本身属于 URI 的特殊字符进行编码,例如冒号、正斜杠、问号和井字号

encodeURIComponent():对它发现的任何非标准字符进行编码

可以对URI进行编码,以便发送给浏览器。

对 URI 进行编码,它们用特殊的 UTF-8 编码替换所有无效的字符,从而让浏览器能够接受和理解。

2.eval方法

通过 eval()执行的代码被认为是包含该次调用的执行环境的一部分,因此被执行的代码具有与该执行环境相同的作用域链

(8.3-8.4)自我充电

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354