《JavaScript权威指南》笔记

102 阅读28分钟

1.词法结构

标志符:必须以字母、\_或者$开头,后续可以是字母、数字、_或者$

2.类型、值和变量

2.1 Javascript类型:

原始类型:字符串、布尔值、数值、undefined、null、symbol(符号类型)

对象类型:对象、数组、函数


2.2 数值

2.2.1 整数字面量

十六进制:0x或0X开头

八进制:0o或0O开头

二进制:0b或0B开头

2.2.2 浮点字面量

  • 十进制数形式,例如:123.45
  • 科学计数法形式,例如:1.23e2 或 1.23e-2

2.2.3 Javascript中的算术

主要包括Math 函数

Math.开头的函数

如Math.ceil(向上舍入)、Math.floor(向下舍入)、Math.pow(2,6)(求2的6次方)、Math.round(四舍五入)、Math.max(求最大值)、Math.min(求最小值)

Javascript中的一些运算准则:

上溢出、下溢出和被零除不会报错

正上溢出(Infinity)、负上溢出(-Infinity)、正下溢出(比最小可表示数值更接近0,则为0)、负下溢出(-0)

正零和负零相等,即使在严格模式下:

被0除返回无穷或者负无穷

0除以 0结果为NaN

NaN与任何数值和非数值都不相等(两个NaN不相等)

所以不能用x===NaN来判断x的值是非数值,只能用(x!=x和Number.isNaN(x)来判断)

2.2.4 BigInt表示任意精度整数

表示方法:一串数字后面+小写字母n

BigInt()函数用于把数值或者字符串转换为BigInt值

BigInt(string)结果10n**100n

0==0n   true

0===0n   false

Math对象的人和函数不接受BigInt操作数


2.3 文本

2.3.1 字符串字面量

反斜杠的特殊用法

'two\nlines'  写在一行但表示两行

‘one\

long\

line’  写在多行但只有一行

2.3.2 字符串API

S.length

S.substring(1,4)  第二到四个字符

S.slice(1,4)  s.slice(-3)  最后三个字符

S.indexOf(“a”)  搜索第一个a 字符出现的位置,没找到返回-1

S.lastIndexOf(“a”) 搜索最后一个a出现的位置

 

 

ES6之后新增

s.startWith(“hello”)   s.endWith(“hello”) 字符串是不是以这些字符开头或结尾的

S.includes(“hello”)   s是不是包含该子串

S.replace(“a”,”b”)  用b替换a

S.toLowerCase()、S.toUpperCase() 全部转换为大写和小写字母

S.charAt(0) S[0] 获取字符串中指定位置的字符

“x”.padStart(3,””)、”x”.padEnd(3,””) 在左侧或者右侧填充字符使其长度变为3,如第二个参数省略,则用空格填充

“test”.trim()、”test”.trimStart()、”test”.trimEnd()  删除左右侧、左侧、右侧的空格

s.concat(“!”)  s+”!” 连接两个字符串

“2”.repeat(5)  重复5次

 

JS中的字符串不可修改,以上操作都返回一个新字符串

2.4 布尔值

假性值:false、undefined、null、’’、NaN、0、-0 在需要布尔值的地方返回false,其他返回true

但是undefined == false返回 false

2.5 null和undefined

typeof(null)  返回object

null==undefined   null!==undefined

2.6 全局对象

全局函数:isNaN()、parseInt()、eval()(?)

全局常量:undefined、Infinity、NaN

构造函数:Date()、RegExp()、String()、Object()、Array()

全局对象:Math、json

Node全局对象:global

浏览器:window

ES2020:Node和浏览器:globalThis

2.7 是否可修改

JS中undefined、null、布尔值、数值、字符串都不可修改

原字符串不可修改 ,对字符串操作之后会返回一个新字符串

对象和数组可以修改,而且是引用  把对象赋值给一个变量,是在赋值引用,不会创建对象的副本,复制数组可以使用Array.from创建副本而不是引用

转存失败,建议直接上传图片文件

2.8 类型转换

转为字符串转为数值转为布尔值
Undefined“undefined”NaNfalse
Null“null”0false
true“true”1 
false“false”0 
“”(空字符串) 0false
“1.2”(非空字符串,数值) 1.2true
“one”(非空字符串,非数值) NaNtrue
0“0” false
-0“0” false
1(有限,非零)“1” true
Infinity“Infinity” true
-Infinity“-Infinity” true
NaN“NaN” false
{}对象  true
[](空数组) 0true
[9](一个数值元素)“9” true
[‘a’]任何其他数组Join方法NaNtrue
Function(){}(任何函数) NaNtrue

 

2.8.1 转换与相等

Undefined==null    true

Undefined==false    false

0==false  true(布尔值转换为数值0)

“0”==false  true(两个操作数都转换为0)

 

==操作符不会将其他操作数转换为布尔值

2.8.2 显示转换

显示转换为数值、字符串或者布尔值的三个函数Number()、String()、Boolean()

常用的隐式转换:

X+”” 转为字符串

+x  转为数值

X-0 转为数值

!!x 转为布尔值

 

数值向字符串的特殊转换,四舍五入

let n = 123456.789;

n.toFixed(m)  m指定的小数位数

n.toExponential(m) 转为科学计数法,小数点前1位,小数点后m位

n.toPrecision(m) 指定有效位数个数m

 

parseInt()、parseFloat()将字符串转为整数或者浮点数会忽略开头的空格和后面的无关字符,如果第一个字符是非空格非数值,则返回NaN

parse可以解析0x或0X开头的字符串

Number只能处理基数为10的,且不能处理后面为无关字符的

parseInt可以接受第二个参数,指定要解析的基数

如:parse(“077”,10)  77

parse(“077”,8)    63

2.9 对象到原始值转换

对象到布尔值的转换:所有对象都转为true

对象转为字符串:

转存失败,建议直接上传图片文件

2.10 变量声明与赋值

2.10.1 var、const和let

通过var实现的全局变量被实现为全局对象的属性,可以通过globalThis来引用(如 var x =10;等价于globalThis.x =10);通过const和let声明的变量不是全局对象的属性。

2.10.2 解构赋值

3.表达式与操作符

3.1 属性访问表达式

ES2020新增属性访问表达式

Expression?.identifier

Expression?.[expression]

?左侧为undefined或者null时会返回Undefined,不会继续往下求值

a?.b 如果a不存在或a.b不存在返回undefined

可选链式求值,如果遇到?左侧为undefined或者null立即返回不会抛出错误

Let a = {b:null};

a.b?.c.d  undefined

(a.b?.c).d   TypeError

Let a = {b:{}}中a.b不是null也不是undefined所以继续求值,a.b?.c?.d返回undefined

转存失败,建议直接上传图片文件

3.2 调用表达式

使用?.()来调用函数,如果?左侧是undefined或null则返回undefined,但是不能检查?左侧是不是函数定义

比如调用log函数,log?.(x)

3.3 对象创建表达式

如:new Object()或者new Object

不传参括号可以省略

3.4 算术表达式

**幂运算具有右结合性

223相当于 2**8

JS中所有数值都是浮点数,所以5/2=2.5不是2

%操作结果的符号与第一个操作数符号相同,-5%2=-1

%操作可以用于浮点数,6.5%2.1=0.2

3.4.1 +操作符

只要有一个操作数是字符串或者可以转为字符串的对象,都执行字符串拼接

以下为字符串拼接:

“1”+2   “12”

1+{}   1[object object]

以下转为数值后再进行运算:

True+true  2   

1+null  1

2+undefined  NaN

3.4.2 一元操作符

++自增操作符始终将操作数先转为数值后再进行自增运算

3.4.3 位操作符

& | ~ ^

<<左移(新的第一位(右)用0填充)

有符号右移(左边的位用符号位填充)

零填充右移(左边的位用0填充)

3.5 关系表达式

3.5.1 不相等和不严格相等

!=和!==分别是==和===的对立面

对象和数组的==和===比较的是地址值

字符串与数值的==,把字符串转为数值后在进行比较

对象与数值或字符串的==,将对象转为原始值再比较    怎么转为原始值?

首先尝试用valeof(),再尝试toString();Date是个例外,执行toString()

3.5.2 比较操作符

+与<的区别

+偏向字符串,只要有一个操作符是字符串就执行拼接操作;<偏向数值,只要有一个操作符是数值就执行比较操作

“11”<3   false  “11”转为数值

3.5.3 in

in操作符左侧操作数是字符串、符号或者可以转换为字符串的值,右侧操作数是对象,如果左侧是右侧的属性名则返回true。

let data = [7,8,9];  数组包括索引

“0” in data   true

1 in data  true  数值1转为字符串

3.5.4 instanceof操作符

Instanceof:需要理解原型链

左侧操作数是对象,右侧操作数是对象的类

let d = new Date();

d instanceof Date;  true

d instanceof Object  true

左侧操作数不是对象返回false;右侧操作数不是对象的类,返回TypeError。

3.6 逻辑表达式

(a===b)&&stop()

3.7 求值表达式

eval

3.8 其他操作符

3.8.1 先定义??

??的作用类似||,||左侧为false才对右侧求值,??在左侧求值为null或者undefined时才求值右侧。

如果混用??和||或者&&中的某一个,必须加圆括号指明先执行什么,否则会报错。

3.8.2 typeof操作符

typeof操作符的返回值

xTypeof x
undefined“undefined”
null“object”
任意值或NaN“number”
任意函数“function”
任意字符串“string”
任意符号“symbol”
任意非函数对象“object”
true或者false“boolean”
任意BigInt“bigint”

 

3.8.3 delete操作符

delete是一元操作符,删除操作数指定的对象属性或数组元素

不可配置属性无法删除

let a = [1,2,3];

delete a[2];

a.length   3

删除数组某个值,该值不存在了但是数组长度没有变化

4.    语句

4.1 for/of

for of用于可迭代对象,可迭代对象一般包括数组、字符串、集合和映射

对象:

对象默认不可迭代,如果想迭代对象的属性可以使用for/in或者for of Object.keys(o);迭代对象的值for of Object.values(o);如果想迭代属性和值对,使用for [key,value] of Object.entries(o)(返回一个数组的数组,[key,value]用于解构。for/of不会迭代继承的属性。

set 和map:

for of可以迭代set和map,迭代map时,

let m = new map([[1,”one”]]);

for(let [key,value] of m){

}迭代出key和value

 

4.2 for/in

for/in可以用于任意对象迭代。For/in不迭代枚举名字为符号的属性,对于名字为字符串的属性,只迭代可遍历的属性;继承的属性也可以被迭代。

 

5.    对象

对象有名字和值还有writable(可写)、enumerable(可枚举)、configurable(可配置)属性。

可写:是否可以设置属性的值;

可枚举:是否可以用for/in循环返回属性名;

可配置:是否可以删除属性以及是否可以修改其特性。

属性名可以是任意字符串包括空字符串。

5.1 创建对象

5.1.1 对象字面量

属性名包含空格和连字符要使用字符串字面量。

let o = {x:1,y:2};

5.1.2 使用new创建对象                     

new+构造函数()

5.1.3 Object.create创建对象

Object.create 的使用:

(1)let o = Object.create({x:1;y:2});

(2)let o = Object.create(Object.prototype);

创建一个空对象

(3)let o = Object.create(null);

创建没有原型的对象,通过这种方式创建的新对象不会继承任何东西,包括toString方法等

5.2 查询和设置属性

属性名需要使用[]操作符不能使用.操作符的情况:

不能写死的属性要用[]而不能用.

比如:动态设置属性名

function(portfolio,stockname,shares){

portfolio[stockname] = shares;

}

5.2.1 属性访问错误

查询已存在对象的不存在的属性是undefined不是错误;但是查询不存在对象的属性是错误TypeError。在null或者undefined上设置属性也会导致TypeError。

防止出现错误的访问方式:

surname = book&&book.author&&book.author.surname;  返回null或者undefined或者surname。

ES2020新语法:

Surname = book?.author?.surname;

5.3 删除属性

采用delete删除属性,只能删除自有属性不能删除继承属性。Delete不可删除不可配置属性。

在严格模式下删除全局属性必须使用delete globalThis.x,非严格模式下可以使用delete x。

Delete使用起来需要小心,操作成功或者没有影响都返回true(删除已删除的属性、删除toString等、删除不存在的属性也返回true。),删除失败才返回false。

5.4 测试属性

测试对象是否含有某个属性。可以使用****in 、hasOwnProperty() 、propertyIsEnumerable() 或者直接查询相应属性,均可用于字符串或者符号作为属性名。

in: 可以测试自有属性和继承属性。  “x” in o

hasOwnProperty :测试自有属性不包含继承属性。O.hasOwnProperty(‘x’)

propertyIsEnumerable: 测试自有且可枚举属性。(常规创建的属性都是可枚举的,除非设置为不可枚举)

in操作符可以区分存在但设为Undefined的属性

let o = {x:1};

“x” in o    true

delete o.x 

“x” in o     false

5.5 枚举属性

for in 循环可以遍历枚举属性和继承属性

获取属性名数组的方法:

Object.keys():只返回可枚举属性,不包含不可枚举、继承、符号属性;

Object.getOwnPropertyNames:自有字符串属性,可枚举和不可枚举;

Object.getOwnPropertySymbols:符号自有属性,可枚举和不可枚举;

Reflect.ownKeys:返回所有属性名,可枚举、不可枚举,字符串、符号属性皆可。

5.6 扩展对象

Object.assign()接收多个参数,第一个参数是目标对象,会被修改;后面的是来源对象,将来源对象的可枚举自有属性复制到目标对象。

第一个来源对象会覆盖目标对象的同名属性,第二个来源对象会覆盖第一个来源对象的同名属性。

转存失败,建议直接上传图片文件

5.7 序列化和恢复对象

JSON.stringify()序列化对象

JSON.parse()恢复对象

5.8 对象方法

对象Object.property上的方法,以下方法在具体的类中都需要重写。

5.8.1 toString()

在对象上使用toString()得到[object object]。

5.8.2 toLocalString

  object的toLocalString没有实现本地化,只是简单的调用toString然后返回该值。

5.8.3 valueOf方法

  用于把对象转换为数值。

5.8.4 一些例子

一、JS Array

例子:

1234Var array = new Array("niu","li","na");console.log(array.valueOf());console.log(array.toString());console.log(array.toLocaleString());

结果:

IMG_256转存失败,建议直接上传图片文件

valueOf:返回数组本身

toString():把数组转换为字符串,并返回结果,每一项以逗号分割。

toLocalString():把数组转换为本地数组,并返回结果。

二、JS Boolean

例子:

123var boolean = new Boolean();console.log(boolean.valueOf());console.log(boolean.toString());

结果:

IMG_257转存失败,建议直接上传图片文件

valueOf:返回 Boolean 对象的原始值。

toString():根据原始布尔值或者 booleanObject 对象的值返回字符串 "true" 或 "false"。默认为"false"。

toLocalString() :Boolean 对象没有toLocalString() 方法。但是在Boolean 对象上使用这个方法也不会报错。

三、JS Date

例子:

1234var date = new Date();**console.log(date.valueOf());**console.log(date.toString());console.log(date.toLocaleString());

结果:

IMG_258转存失败,建议直接上传图片文件

valueOf:返回 Date 对象的原始值,以毫秒表示。

toString():把 Date 对象转换为字符串,并返回结果。使用本地时间表示。

toLocalString():可根据本地时间把 Date 对象转换为字符串,并返回结果,返回的字符串根据本地规则格式化。

四、JS Math

例子:

1console.log(Math.PI.valueOf());

结果:

IMG_259转存失败,建议直接上传图片文件

valueOf:返回 Math 对象的原始值。 

五、JS Number

例子:

1234var num = new Number(1337);console.log(num.valueOf());console.log(num.toString());console.log(num.toLocaleString());

结果:

IMG_260转存失败,建议直接上传图片文件

valueOf:返回一个 Number 对象的基本数字值。

toString():把数字转换为字符串,使用指定的基数。

toLocalString():把数字转换为字符串,使用本地数字格式顺序。

六、JS String

例子: 

123var string = new String("abc");console.log(string.valueOf());console.log(string.toString());

结果:

IMG_261转存失败,建议直接上传图片文件

valueOf:返回某个字符串对象的原始值。

toString():返回字符串。  

七、toString()方法与toLocalString()方法区别

toLocalString()是调用每个数组元素的 toLocaleString() 方法,然后使用地区特定的分隔符把生成的字符串连接起来,形成一个字符串。

toString()方法获取的是String(传统字符串),而toLocaleString()方法获取的是LocaleString(本地环境字符串)。

如果你开发的脚本在世界范围都有人使用,那么将对象转换成字符串时请使用toString()方法来完成。

LocaleString() 会根据你机器的本地环境来返回字符串,它和toString() 返回的值在不同的本地环境下使用的符号会有微妙的变化。

所以使用toString()是保险的,返回唯一值的方法,它不会因为本地环境的改变而发生变化。如果是为了返回时间类型的数据,推荐使用LocaleString()。若是在后台处理字符串,请务必使用****toString()

5.9 对象字面量扩展语法

5.9.1扩展属性

...用于把a和b的属性展开放入c中。

let a = {x:1;z:2};

let b = {y:2};

let c = {...a,...b};

扩展操作符只扩展自有属性,不扩展继承属性。

 

5.9.2 简写方法

ES6之前:

let square = {

area:function(){

this.side*this.side;

}

}

ES6之后,function可以省略。

let square = {

area(){

this.side*this.side;

}

}

以上简写语法写方法时,属性名可以是对象字面量允许的任何形式。

5.9.3 属性的get和set

转存失败,建议直接上传图片文件

6.    数组

JS数组中的不同元素可以是不同的类型;也可以是对象或者数组;数组可以是稀疏的,即不一定具有连续的索引。

数组从Array.prototype继承属性。

ES6新增定型数组。

6.1 创建数组

6.1.1 数组字面量

let count = [1,,3];  索引1没有数值,按索引访问时返回undefined

let undefs = [,,];  该数组没有元素,长度为2,数组字面量语法允许末尾出现逗号

6.1.2 扩展操作符

let a = [1,2,3];

let b = [0,...a,4];  b的值为0,1,2,3,4

数组去重的方法:将数组转为set去重后再转回来

let letters = [...”hello world”];

[...new Set(letters)]   结果为[‘h’,’e’,’l’,’o’,’’,’w’,’r’,’d’]

6.1.3 Array()构造函数

let a = Array(10);  创建一个长度为10的数组,数组没有存储任何值,数组索引“0”、“1”等没有意义。

传入Array()构造函数的参数个数大于1时,参数代表数组元素。

所以使用Array()构造函数无法创建一个只含有一个特定值的数组。

6.1.4 Array.of()函数

使用Array.of()可以创建一个含有特定值的元素。

Array.of(10)  创建一个只含有元素10的数组

Array.of(1,2,3)  创建一个含有元素1,2,3的数组

6.1.5 Array.from()函数

Array.from()用于创建数组的副本。

Array.from()函数接受一个或者两个参数,如果有第二个参数,第二个参数是一个函数,第一个参数数组中的每一个值都会经过该函数的处理再返回。

转存失败,建议直接上传图片文件

6.2 可读写数组元素

数组是对象,索引可以使用字符串等,但是只有所以为数值0-2^32-2之间才会为数组添加长度length属性。

查询对象中不存在的属性会返回undefined。

6.3 稀疏数组

稀疏数组的判定:length值大于元素个数

方法一: let a = Array(5)    创建了一个长度为5但是没有元素的数组

方法二:

转存失败,建议直接上传图片文件

方法三:

let a = [,];

方法四:

let b = [undefined,undefined];

6.4 数组长度

如果将数组长度强行设置为小于数组元素个数的值,数组中length之后的值会被删除

6.5 添加或删除数组元素

尾部添加:a.push

首部添加:a.unshift

删除:delete a[2]  删除元素相当于把数组该索引处值设为undefined,不会改变数组长度,会使数组变为稀疏数组

6.6 数组迭代

for/of:不能感知稀疏数组  如果想得到数组索引,使用for(let[index,item] of a.entries())

forEach:可以感知稀疏数组

6.7 多维数组

访问元素a[x][y]

6.8 数组方法

6.8.1数组迭代器方法

这类方法对于稀疏数组,不会对不存在的数组元素调用传入的这个参数。

一、forEach

参数是一个函数,可以接收三个参数,第一个参数是元素值,第二个参数是元素索引,第三个参数是数组对象,第二、三个参数可以省略。forEach没有提前终止的方式,类似break这种。

转存失败,建议直接上传图片文件

二、Map

Map()方法用于对每个元素进行处理并将处理结果返回给该元素。Map()返回一个新数组,并不修改调用它的数组。forEach 可以修改调用它的数组。

转存失败,建议直接上传图片文件

三、Filter

可以接受三个参数

转存失败,建议直接上传图片文件

过滤稀疏数组,只保留有值的元素

A.filter(()=>true)

转存失败,建议直接上传图片文件

清空空隙删除Undefined和null

A.     filter(x=>x!=null&&x!=undefined)

四、every和some

均返回true或者false  

a.every(x=>x>0)   在第一次返回false时就停止返回false

a.some(x=>x>0)    在第一次返回true时就停止返回true

对于空数组,every返回true;some返回false

转存失败,建议直接上传图片文件

五、find和findIndex

均接收一个函数

find返回第一个匹配的元素,没找到返回undefined;findIndex返回第一个匹配的元素的索引,没找到返回-1

六、reduce和reduceRight

reduce:归并,接收两个参数,第二个参数表示传给归并函数的初始值。

let a = [1,2,3,4,5];

a.reduce((x,y)=>x+y,0)  //15

a.reduce((x,y)=>x*y,1)   //120

a.reduce((x,y)=>x>y?x,y)  //5

reduceRight从高索引开始归并

 

6.8.2 打平数组

flat():打平数组

不传参调用,打平一级嵌套

let a = [1,[2,3],[[4]],[[[5]]]];

a.flat(4)   [1,2,3,4,5]

flatMap() 与map 方法相似,只不过返回的结果会被自动打平

let phrases = [“hello world”,”the definitive guide”];

let words = phrases.flatMap(phrase=>phrase.split(“”));

words     [“hello”,”world”,”the”,”definitive”,”guide”]

flatMap 允许把输入元素映射为空数组

[-1,-2,1,4].flatMap(x=>x<0?[]:Math.sqrt(x))   [1,2]

6.8.3 使用concat()

会返回一个新数组

concat接收多个参数,如果参数中含有数组,会将数组打平,但是不会嵌套打平

let a = [1,2];

a.concat(3,[4,[5,6]])   //[1,2,3,4,[5,6]]

6.8.4 push、pop、shift和unshift

这四个方法会修改原数组

在数组末尾的操作: push、pop

push返回新数组长度;pop返回删除数组的值

在数组开头的操作: shift和unshift

unshift返回新数组长度;shift返回删除元素的值

使用unshift时需要注意:

let a = [1];

a.unshift(2);  //a:[2,1]

a.unshift(3);   //a:[3,2,1]

对比:

let a = [1];

a.unshift(2,3);  //a:[2,3,1]

6.8.5 slice()、splice()、fill()和copyWithin()

一、slice()

接收两个参数,代表切片的起点和终点,如果任何一个参数是负值则表示相对于数组长度的指定数组元素,比如-1代表最后一个元素,-2代表倒数第二个元素。

二、splice

会修改数组,可以对数组进行插入和删除。如果只有两个参数,表示对数组进行删除,并将返回值创给数组。

splice的第一个参数指定插入或删除操作的起点位置,第二个参数指定从数组中删除的元素个数。第三个参数及之后的参数表示要插入数组中的元素。如果插入的是数组,splice不会打平插入的数组,concat会打平一层嵌套数组。

let a = [1,2,3,4,5];

a.splice(2,2)  //从位置2开始删除,删除长度为2,结果为a ==[1,2,5]

let a = [1,2,3,4,5];

a.splice(2,2,[6,7],3)     //a==[1,2,[6,7],3]

三、fill

可以接收三个参数,第一个参数表示要填充的值,第二个可选参数表示填充的起始索引,第三个可选参数表示填充的终止索引。

不能如下:

转存失败,建议直接上传图片文件

可以如下:

转存失败,建议直接上传图片文件

四、copyWithin

把数组切片后复制到数组中指定位置,会就地修改数组,但不会改变数组长度。可以接收一个、两个或三个参数。第一个参数表示要复制到的位置,第二个参数表示复制的起始索引,第三个参数表示要复制的终止索引。

如下:要复制的元素过长,会进行截取,数组长度不会改变。

转存失败,建议直接上传图片文件

6.8.6 数组索引与排序方法

一、indexOf()和lastIndexOf()

indexOf()和lastIndexOf()从数组中搜索指定的值并返回第一个找到的元素的索引;

indexOf从低索引开始找,lastIndexOf从高索引开始找;

均接收第二个可选参数,表示开始寻找的起始索引;如果没有找到返回-1。

用法indexOf(1,2),寻找1,从索引2开始找

indexOf和findIndex都可以从数组查找元素,indexOf接受一个具体值,findIndex接受一个函数。

二、includes()

includes()参数接受一个参数,如果数组包含该值返回true,否则返回false。

let a = [1,NaN];

a.includes(NaN);    //true

includesOf()可以检测NaN,indexOf()无法检测NaN

三、sort()

sort()在不传参时按照字母顺序排序。接收参数是函数。

转存失败,建议直接上传图片文件

所以在对数值排序时,需要传参

四、reverse()

反转数组顺序,就地修改数组。

6.8.7 数组到字符串的转换

join()或者toString()

toString()与不传参的join()实现效果一样。

转存失败,建议直接上传图片文件

6.8.8 静态数组函数

用于确定一个未知值是不是数组。

Array.isArray([])     //true

Array.isArray({})     //false

7.函数

7.1 函数定义

7.1.1 函数声明

函数声明可以出现在块语句中,不过块语句中的函数只能在该块中有定义,对块的外部不可见。

7.1.2 函数表达式

使用函数声明形式,在作用域内,可以在函数定义之前调用函数,因为存在变量提升;使用函数表达式形式,在定义函数之前不能调用函数,在定义之前函数是undefined。

7.1.3 箭头函数

箭头函数如果想要返回对象需要写成如下形式:

const functionX = x=>{{value:x}};   // 必须使用两个括号

7.2 函数调用

7.2.1 函数的this

非严格模式下,函数的this指window;严格模式下,this是undefined。

7.2.2 作为方法

将函数添加为某个对象的方法,o.m = f;作为方法的函数的this指向该对象而不是window。

在函数中可以嵌套定义函数,在方法中嵌套定义的函数的this 是window 而不是该对象。

let o = {

m:function(){

let self = this;

this === o ;   //true

f();


function f(){

this === o;   //false

self === o;   //true;

}

}

}

在ES6 中嵌套函数写成箭头函数也可以解决这个问题。函数f 重写为

const f = ()=>{

this === o; //true

}

或者:

const f = (function(){

this === o;

}).bind(this);

7.2.3 构造函数调用

构造函数如果没有参数可以省略圆括号;

 o = new Object();  等价于 o = new object;

构造函数正常情况下不会使用return关键字;而是初始化新对象并在到达函数体末尾时隐式返回这个对象。

如果显示的使用return返回某个对象,该对象就会成为调用表达式的值;如果使用了return但没有返回值或者返回的是一个原始值,这个返回值就会被忽略,仍以先创建的对象作为调用表达式的值。

7.2.4 间接调用

JS **函数也是对象,它也有两个方法call() ****和apply() **,可以用来间接调用函数。

这两个方法允许指定调用时this 的值,意味着可以将任意函数作为任意对象的方法来调用,即使这个函数并不是该对象的方法。

7.3 函数实参与形参

7.3.1 可选形参与默认值

如果实参个数小于形参则额外的形参会获得undefined值。

function f(a,b){

b||[]      //如果形参b没有值就用[]代替

}

默认值的使用:

function f(a,b=[]){

}

可以使用前面的形参给后面的形参传值:

function f(a,b=2*a){

}

7.3.2 剩余形参与可变长度实参列表

如果实参个数大于形参个数,使用剩余形参。

f(a,b,c,d)

function f (a,b,...c){

}

7.3.3 Arguments对象

arguments是一个类数组(元素类型可以不同),是实参列表数组

例如:

function max(x){

  let maxValue = -Infinity;

  for(let i = 0;i<arguments.length;i++)

   {

if(arguments[i]>maxValue)

maxValue = arguments[i];

}

return maxValue;

}

7.3.4 在函数调用中使用扩展操作符

let numbers = [1,2,3,4,5];

Math.min(...numbers);  //1

7.3.5 函数实参解构为形参

function a({x:x1,y:y1,z=0},{x:x2,y:y2})

{

}

a({x:1,y:2},{x:3,y:4})

解构对象和解构数组都可以使用剩余形参

function a({x:x1,y:y1,...rest},{x:x2,y:y2})

{

}

a({x:1,y:2,z:5,o:33},{x:3,y:4})

7.3.6 参数类型

如果实参与期待的参数类型不匹配,JS会进行自动类型转换。

7.4 定义函数属性

函数也是对象,可以为函数设置属性。

counter 是函数uniqueInteger 函数的一个属性

转存失败,建议直接上传图片文件

factorial() 函数使用自身的属性来缓存之前的计算结果(函数将自身作为一个数组)

用函数名来保存变量

转存失败,建议直接上传图片文件

7.5 函数作为命名空间

在函数内声明的变量在函数外部不可见。可以把函数作为临时的命名空间,这样可以保证在其中定义的变量不会污染全局命名空间。

其中一个应用:立即调用函数表达式IIFE

(function(){}());

另一个应用:闭包

7.6 闭包

P188

例一:

以下利用闭包把counter 放在私有作用域内;

uniqueInteger 在全局作用域内,所以多次调用时counter 会在上次的值上进行累加,作用域没有销毁 ???

let uniqueInteger = (function() {  // Define and invoke

    let counter = 0;               // Private state of function below

    return function() { return counter++; };

}());

uniqueInteger()  // => 0

uniqueInteger()  // => 1

例二:

function counter() {

    let n = 0;

    return {

        count: function() { return n++; },

        reset: function() { n = 0; }

    };

}

 

let c = counter(), d = counter();   // Create two counters

c.count()                           // => 0

d.count()                           // => 0: they count independently

c.reset();                          // reset() and count() methods share state

c.count()                           // => 0: because we reset c

d.count()                           // => 1: d was not reset

通过let c = counter(), d = counter();c和d都在全局作用域中,所以每次调用d.count都会在原值基础上自增。c 和d 互不影响。

例三:私有状态传入

没有声明局部变量,只使用自己的参数n 保存供属性访问器共享的私有状态。这样可以让counter() 调用者指定私有变量初始值。

function counter(n) {  // Function argument n is the private variable

    return {

        // Property getter method returns and increments private counter var.

        get count() { return n++; },

        // Property setter doesn't allow the value of n to decrease

        set count(m) {

            if (m > n) n = m;

            else throw Error("count can only be set to a larger value");

        }

    };

}

 

let c = counter(1000);

c.count            // => 1000

c.count            // => 1001

c.count = 2000;

c.count            // => 2000

c.count = 2000;    // !Error: count can only be set to a larger value

例四:以下两份代码对比 重要

以下funcs5的结果为5

转存失败,建议直接上传图片文件

funcs5的结果为10

转存失败,建议直接上传图片文件

7.7 函数属性、方法和构造函数

7.7.1 length属性

length代表形参个数

转存失败,建议直接上传图片文件

7.7.2 name属性

表示定义函数时使用的名字

转存失败,建议直接上传图片文件

7.7.3 prototype属性

除了箭头函数所有函数都有prototype属性。

 

 

 


数值字面量的分隔符

数值字面量可以使用分隔符分隔为更为清楚的字段:

如:1_000_000,千位分隔符;0x89_ab_cd_ef,字节分隔符;0b0001_1101,半字节分隔符;0.123_456_789,小数点后分隔符