js笔记
Last updated on a day ago
基础语法
Hello World
1 |
|
JavaScript书写位置
共有三种写法
行内、script、外部js文件中
行内
新建一个 haicoder.html 文件,并输入以下内容:
1 |
|
代码运行
当我们点击按钮时,运行onclick中的代码
script标签
1 |
|
使用外部js文件
新建一个main.js文件
1 |
|
然后再新建一个main.html文件
1 |
|
JavaScript是弱类型语言
JavaScript 是弱类型语言,因此 JavaScript 变量 无须声明可以直接赋值。
并且 JavaScript 变量的 数据类型 可以动态改变,即同一个变量可以一会儿被赋值为 整数值,一会儿也可以被赋值为字符串。
变量
JavaScript 是弱类型语言,因此 JavaScript 变量无须声明可以直接赋值。
变量声明
在 JavaScript 中 ,声明变量使用 var 关键字,var 关键字后面直接加变量名即可。
1 |
|
声明并复制
1 |
|
多个声明变量并赋值
1 |
|
改变类型
JavaScript是弱类型语言,变量的数据类型可以改变
1 |
|
代码运行
按下f12打开浏览器控制台,查看结果
变量命名规则和规范
规则
- JavaScript 变量只能由字母、数字、下划线、$ 符号组成,不能以数字开头。
- JavaScript 变量命名时不能使用 关键字 和保留字,例如:for、while。
- JavaScript 变量命名是区分大小写的,即变量 a 与变量 A 是两个不同的变量。
规范和建议
遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。例如:userName、userPassword 等。
建议:
在给变量命名时,我们要做到见名知意,同时,我们最好也能做到见到变量名,能知道变量的 数据类型 ,因此,在定义变量时也有一套类似的常识标准,即,我们使用不同的变量前缀,代表变量的不同数据类型,如下:
类型 | 前缀 | 类型 | 实例 |
---|---|---|---|
数组 | a | Array | aItems |
布尔 | b | Boolean | bIsPass |
浮点数 | f | Float | fPrice |
函数 | fn | Function | fnHandler |
整数 | i | Integer | iCount |
对象 | o | Object | oPerson |
正则表达式 | re | RegExp | reEmailCheck |
字符串 | s | String | sUserName |
数据类型
基本数据类型
JavaScript 的基本数据类型有六种,即:字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、代表(Symbol)。
其中代表是在 ECMAScript 6 中新添加的类型。一种实例是唯一且不可改变的数据类型。
字符串不能改变
其中数值、字符串、布尔称为原始类型,是最基本的数据类型,不能再细分。
同时,这些类型又有值类型和引用类型。
- 值类型:Number、String、Boolean、null、undefinded
- 引用类型:函数、对象、数组等
值类型传递的是值,比如将变量a赋值给变量b,只传递值的话,两者只是单纯的值相等,没有其他关联,改变其中一个对另一个没有影响。如:而如果是引用类型,比如数组,则对另一个的修改会影响另一个1
2
3
4
5var a = 100;//Number类型,值传递
var b = a;//赋值
b = 10;
console.log(a);//将a输出到浏览器控制台,100
console.log(b);//将b输出到浏览器控制台,101
2
3
4
5var c = new Array(1,2,3);//声明数组[1,2,3]
var d = c;
d[0] = 0;[将d数组的1改为0]
console.log(c);//输出[023]
console.log(d);//输出[023]
JavaScript复杂数据类型
JavaScript 的复杂数据类型只有一种,即 Object。对象则称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。
字符串
JavaScript 中的字符串是一串表示文本值的不可变的字符序列,JavaScript 的字符串使用** String 对象**来表示。声明 JavaScript 字符串语法:
数字
JavaScript 中的数字可以分为整数和 浮点数 类型,JavaScript 的数字使用 Number 对象来表示。JavaScript 的整数还可以分为二进制、八进制、十进制和十六进制形式。
进制声明
1 |
|
浮点数
JavaScript 的浮点数使用 Number 对象来表示。JavaScript 的浮点数有两种表现形式,第一种就是用普通的小数表示法、第二种就是使用科学计数法。
数字范围
JavaScript 数字的最大值和最小值都可以使用 Number 里面的常量值来获取。
1 |
|
NaN
JavaScript 中 NaN 属性是代表非数字值的特殊值,该属性用于指示某个值不是 数字。可以把 Number 对象设置为该值,来指示其不是数字值。
NaN 与任何值都不相等,包括其本身。也就是说NaN==NaN是false
同时将一个非数字的变量转为数字,会返回NaN
isNaN函数:用于判断传入的 变量 是否不是一个 数字,如果是一个数字,则返回 false,否则,返回 true。
1 |
|
布尔
JavaScript 中的 true 在内部存储的值是 1,JavaScript 中的 false 在内部存储的值是 0。
1 |
|
undefined
JavaScript 中的 Undefined 表示 变量 未定义时的属性,当读取不存在的 对象 属性时会返回 undefined。
1 |
|
null
JavaScript 中的 null 是一个表明 null 值的特殊 关键字。 JavaScript 是大小写敏感的,因此 null 与 Null、NULL 或变体完全不同。
JavaScript 中的 null 是可以进行比较的,即 null 等于 null。
1 |
|
null与undefined
JavaScript 中的 null 是 js 中的 关键字,表示空值,null 可以看作是 was object 的一个特殊的值,如果一个 object 值为空,表示这个对象不是有效 对象。
undefined 不是 js 中的关键字,其是一个 全局变量,是 Global 的一个属性。
相同点:都是原始类型的值,保存在栈中变量本地。
不同:
- JavaScript null 与 undefined 类型 不一样。
- 转化为值时不一样,undefined 为 NaN ,null 为 0。
返回underfined的情况: - 使用了一个未定义的变量。
- 使用了已定义但未声明的变量。
- 使用了一个对象属性,但该属性不存在或者未赋值。
- 调用 函数 时,该提供的参数没有提供。
- 函数没有返回值时,默认返回 undefined。
Symbol类型
JavaScript 中的 Symbol 是 ECMAScript 6 中新添加的 类型,是一种实例是唯一且不可改变的数据类型。
1 |
|
而且每个Symbol()变量都是唯一的
1 |
|
同时也正因为这个性质,可以用作对象属性
1 |
|
数据类型转换
toString | 转换成字符串类型 | x.ToString() |
String | 转换成字符串类型 | String(x) |
Number | 转换成数字类型 | Number(x) |
parseInt | 转换成整数类型 | x.parseInt() |
parseFloat | 转换成浮点数类型 | x.parseFloat() |
Boolean | 转换成布尔类型 | Boolean(x) |
将特定的数据类型的变量转成字符串类型可以使用toString()和String方法。有些数据类型没有toString()方法,比如undefined和null,这时候需要用string方法
语法:
1 |
|
转数字
将特定的数据类型的变量转成数字类型可以使用Number()和parseInt()方法
基本语法:
1 |
|
同时转换规则两者也有一定的差别:
当Number遇到无法转换成的字符串比如“123b“会返回NaN,而parseInt则会转换到无法转换为止,即返回123,当radix参数超过范围时,返回NaN
1 |
|
代码运行
与parseInt类似的还有parseFloat()
转布尔
将其他类型转布尔使用Boolean函数。规则如下:
类型 | 规则 |
---|---|
Number | 0为false,非0true |
string | 空为false,其他true |
null | false |
underfined | false |
this指向
- 当以函数的形式调用时, this是window。
- 当以方法的形式调用时, 谁调用方法this就是谁。
- 当以构造函数的形势调用时, this就是新创建的对象。
输出
三种方式
通常可以有三种显示方法,即:以对话框的形式弹出信息、输出文本到浏览器显示和输出文本到浏览器的控制台。
以对话框的形式弹出信息我们使用 window.alert() 方法,输出文本到浏览器显示我们可以使用document.write() 和 innerHTML 方法,输出文本到浏览器的控制台我们使用 console.log() 方法。
1 |
|
alert
显示带有一条指定消息和一个确认按钮的警告框。对话框是一个模态窗口,它能阻止用户对浏览器窗口界面的其他部位进行操作。参数是要显示在对话框中的文本字符串,如果传入其他类型的值,会转换成字符串。
write
在 JavaScript 中 document.write() 方法可向文档写入 HTML 表达式或 JavaScript 代码。同时,一次可列出多个参数(exp1,exp2,exp3,…) ,并将按顺序被追加到文档中。
虽然根据 DOM 标准,该方法只接受单个 字符串 作为 参数。不过根据经验,write() 可接受任何多个参数。
我们通常按照两种的方式使用 write() 方法:一是在使用该方法在文档中输出 HTML,另一种是在调用该方法的的窗口之外的窗口、框架中产生新文档。在第二种情况中,请务必使用 close() 方法来关闭文档。
1 |
|
innerHTML
用于设置或返回表格行的开始和结束标签之间的 HTML。
console方法
方法用于向控制台输出一条消息。同时支持 C 语言 printf 式的格式化输出。当然,也可以不使用格式化输出来达到同样的目的。
console.log()系列方法
console.log | 向控制台输出一条消息。 |
console.debug | 向控制台输出一条信息,它包括一个指向该行代码位置的超链接。 |
console.info | 向控制台输出一条信息,该信息包含一个表示“信息”的图标,和指向该行代码位置的超链接。 |
console.warn | 同 info。区别是图标与样式不同。 |
console.error | 同 info。区别是图标与样式不同。error 实际上和 throw new Error() 产生的效果相同,使用该语句时会向浏览器抛出一个 js 异常。 |
console.assert | 断言,测试一条表达式是否为真,不为真时将抛出异常(断言失败)。 |
1 |
|
变量提升
在 JavaScript 中函数及变量的声明都将被提升到函数的最顶部。因此,在 JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。
变量提升的本质其实是由于 js 引擎在编译的时候,就将所有的变量声明了,因此在执行的时候,所有的变量都已经完成声明。
当有多个同名变量声明的时候,函数声明会覆盖其他的声明。如果有多个函数声明,则是由最后的一个函数声明覆盖之前所有的声明。
1 |
|
代码运行
JavaScript 会将当前作用域的所有变量的声明提升到程序的顶部。如果修改如下,则会报错underfined,因为只有声明会被提升,赋值则不会。
1 |
|
代码运行
当函数与变量同名时,函数的优先级更高
1 |
|
代码运行
可以看见函数被正常调用。如果是多个同名函数,则取后面的
1 |
|
代码运行
现在将代码修改如下:
1 |
|
代码运行
结果是“fun not a function”,这是因为”var fun = function(){}”是一个变量声明赋值语句,var fun也是,两个同名变量取后者,因此fun是undefined
var,let和const
var和let都是用于声明变量的关键字,但存在一定差异:
var 定义变量,没有块的概念,可以跨块访问,不能跨函数访问,不初始化出现undefined,不会报错。
let 定义变量,只能在块作用域里访问,也不能跨函数访问,对函数外部无影响。
const 定义常量,只能在块作用域里访问,也不能跨函数访问,使用时必须初始化(即必须赋值),而且不能修改。(这点有点特殊,后面讲)
var声明的变量作用域在整个函数范围内,或者全局:
1 |
|
运行代码
结果是函数可以正常运行打印出a,说明var声明变量作用域是整个函数
如果换成let:
1 |
|
代码运行
const与let类似。
以及var可以声明相同变量,而let只能声明一次
最后关于const不能修改这点
1 |
|
当const声明的是一个简单类型时,是不能修改的,会报错。
但如果声明的是一个复杂类型(一般是对象和数组),则会出现不同的地方。
1 |
|
没报错,数组被修改。这是为什么呢?
这是因为,const保证的其实是a指向的内存地址不改变,而不是该内存地址的内容不改变。简单类型其实就是常量,无法修改,想改变a的值只能重新指向新地址,但对于数组,他的值改变了,但地址并不会改变,也就不会引起a指向的改变。
严格模式
ECMAScript 5 的严格模式是采用具有限制性 JavaScript 变体的一种方式,从而使代码显示地脱离 “马虎模式/稀松模式/懒散模式“(sloppy)模式。
在 JavaScript 中,我们要开启严格模式,只需要使用 use strict 指令即可。
语法:
1 |
|
放在代码顶部,也可放在函数前,只对函数生效,但一般是全局形式。它不是一条语句,是一个字面量表达式,在 JavaScript 旧版本中会被忽略。
为什么使用严格模式
- 消除 JavaScript 语法的一些不合理、不严谨之处,减少一些怪异行为。
- 消除代码运行的一些不安全之处,保证代码运行的安全。
- 提高编译器效率,增加运行速度。
- 为未来新版本的 JavaScript 做好铺垫。
- “严格模式” 体现了 JavaScript 更合理、更安全、更严谨的发展方向,包括 IE 10 在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它。
- 另一方面,同样的代码,在 “严格模式” 中,可能会有不一样的运行结果;一些在 “正常模式” 下可以运行的语句,在 “严格模式” 下将不能运行。掌握这些内容,有助于更细致深入地理解 JavaScript,让你变成一个更好的程序员。
- 严格模式通过抛出错误来消除了一些原有静默错误。
- 严格模式修复了一些导致 JavaScript 引擎难以执行优化的缺陷:有时候,相同的代码,严格模式可以比非严格模式下运行得更快。
- 严格模式禁用了在 ECMAScript 的未来版本中可能会定义的一些语法。
严格模式的限制 - 不允许使用未声明的 变量。
- 不允许删除变量或 对象。
- 不允许删除 函数。
- 不允许变量重名。
- 不允许使用八进制。
- 不允许使用 转义字符。
- 不允许对只读属性赋值。
- 不允许对一个使用 getter 方法读取的属性进行赋值。
- 不允许删除一个不允许删除的属性。
- 变量名不能使用 “eval” 字符串。
- 变量名不能使用 “arguments” 字符串。
- 由于一些安全原因,在作用域 eval() 创建的变量不能被调用。
- 禁止 this 关键字指向全局对象。
运算符
其他懒得写,写不同的地方就好
比较运算符
不同点就是”===“和”!==“两个运算符,三等号表示等值等型,!==表示不等值或不等型
1 |
|
三目运算符
js支持三目运算符,和三目嵌套
1 |
|
键盘输入
在 JavaScript 中,获取用户输入的数据使用 prompt 方法。
1 |
|
返回值:如果用户单击提示框的取消按钮,则返回 null。如果用户单击确认按钮,则返回输入字段当前显示的文本。
1 |
|
代码运行
再用户输入时,会暂停对js代码的进行。
流程控制
if、elseif、while、for、switch等都与C语言一样,但js的for可以用for in语句,可以用于遍历 数组 的每一个元素或者用于遍历获取 对象 的每一个属性
1 |
|
当使用 for in 循环遍历数组时,那么参数 i 是数组的索引,而不是数组的元素。当使用 for in 循环遍历对象时,那么参数 variable 是对象的属性。
break语句:js的break与C类似,但js可以指定中断的循环
1 |
|
这里loop是标签,后接“:”
continue也有一样的用法
函数
基本形式
JavaScript 的函数可以分为:自定义函数和系统函数。
JavaScript 的函数也支持普通函数、匿名函数 和 闭包 三种形式。
js的函数声明不需要写返回值类型,定义参数也不需要声明类型。
1 |
|
函数参数默认值
如果我们在调用函数时没有输入参数,则使用我们定义的默认参数的值。函数的默认参数必须放在函数参数列表的最后,且默认参数可以是任意多个。
1 |
|
arguments
在 JavaScript 中,arguments 对象是比较特别的一个 对象,实际上是当前 函数 的一个内置属性。也就是说所有函数都内置了一个 arguments 对象。
arguments 对象中存储了传递的所有的 实参,arguments 是一个 伪数组(本质还是对象),因此可以进行遍历。
argument常用方法
函数 | 说明 |
---|---|
arguments.callee | arguments 所在的函数,指向当前执行的函数 |
arguments.caller | 指向调用当前函数的函数 |
arguments.length | 获得长度,实参的个数 |
arguments[i] | 通过遍历索引,获得每个实参 |
函数变量
在js中函数也是一种数据类型,可以和其他类型一样,保存在变量中
1 |
|
匿名函数
匿名函数就是不写函数名的函数,往往赋值给变量。匿名函数的调用方法有四种
1 |
|
闭包
闭包就是一个 函数 和与其相关的引用环境组合的一个整体。
在 JavaScript 中闭包是引用了 自由变量 的函数,被引用的自由变量和函数一同存在,即使已经离开了自由变量的环境也不会被释放或者删除,在闭包中可以继续使用这个自由变量。
闭包(Closure)在某些编程语言中也被称为 Lambda 表达式
在 JavaScript 中,被捕获到闭包中的变量让闭包本身拥有了记忆效应,闭包中的逻辑可以修改闭包捕获的变量,变量会跟随闭包生命期一直存在,闭包本身就如同变量一样拥有了记忆功能。
1 |
|
作用域
作用域有全局、局部、和块级。任意一对花括号中的语句都属于一个块。
js词法规则
- 函数允许访问函数外的数据
- 整个代码结构中只有函数可以限定作用域
- 作用域规则首先使用提升规则分析
- 如果当前作用规则中有名字了, 就不考虑外面的名字
作用域链
只有函数可以制造作用域结构, 那么只要是代码,就至少有一个作用域,即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。
将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。
字符串函数
字符串长度
在 JavaScript 中要想获取字符串长度只需要使用字符串的 length 属性即可。JavaScript 获取字符串长度语法:
1 |
|
截取字符串
在 JavaScript 中,截取字符串有三种方法,分别为:使用 substring 函数、使用 substr 函数和使用 slice 函数。
1 |
|
代码运行
substring和slice的区别:
- slice接受负数,表示从结尾算起
- substring如果结束位置在起始位置之前,会自动调整,而参数小于0时按0处理
拼接字符串
JavaScript 拼接 字符串 有两种方法,分别是:使用 + 号拼接和使用 **join **函数 拼接。
加号直接加就好,join语法如下:
1 |
|
分割字符串
注意分隔和截取的区别
语法
1 |
|
separator为必填,表示从该参数指定的地方开始分隔,可以填字符串或正则表达式。
howmany表示返回数组的最大长度,如果不填则整个字符串都会被分隔
返回值:一个字符串数组,返回的数组中的字串不包括 separator 自身。
但是,如果 separator 是包含子表达式的 正则表达式,那么 返回 的数组中包括与这些子表达式匹配的字串(但不包括与整个正则表达式匹配的文本)。
说明:如果把“”空字符串做spearator做参数,则每个字符都被分隔
1 |
|
查找子字符串
在一个字符串中查找另一个字符串有四种方法,分别为:使用 indexOf 函数、使用 lastIndexOf 函数、使用 match 函数和使用 search 函数。
indexOf
indexOf() 方法可 返回 某个指定的字符串在源字符串中首次出现的位置。如果没有则返回-1
1 |
|
参数 | 描述 |
---|---|
searchvalue | 必需。规定需检索的字符串值。 |
fromindex | 可选的整数参数。规定在字符串中开始检索的位置。它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的首字符开始检索。 |
lastIndexOf()
lastIndexOf() 方法可返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。如果找到一个 searchvalue,则返回 searchvalue 的第一个字符在 stringObject 中的位置。
用法同上
正则表达式匹配字符
在一个 字符串 中使用正则表达式去匹配查找另一个字符串有两种方法,分别为:使用 match 函数和使用 search 函数。
match()
match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。该方法类似 indexOf() 和 lastIndexOf(),但是它 返回 指定的值,而不是字符串的位置。返回个数取决于是否启用全局检索
1 |
|
search()
search()于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。返回匹配子串的起始位置,没有则-1.
search不支持全局模式,但有忽略大小写模式‘i’
访问字符串字符
在 JavaScript 中要想获取 字符串 中某个下标的字符,有三种方法,分别为:使用 [] 加上下标访问、使用charAt函数 访问和使用 charCodeAt 函数访问。
charAt
1 |
|
返回该索引处的字符,如果越界则返回undefined
charCodeAt
1 |
|
如果访问的索引在字符串中,则返回该索引处的字符的ACSII码,否则,返回NaN。
字符串替换
在JavaScript中,在一个 字符串 中将特定的字符串替换为指定的字符串,可以使用 replace 函数。
replace() 函数用来查找匹配一个 正则表达式 的字符串,然后使用新字符串代替匹配的字符串。
1 |
|
参数 | 描述 |
---|---|
regexp/substr | 必需。规定子字符串或要替换的模式的 RegExp 对象。请注意,如果该值是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为 RegExp 对象。 |
replacement | 必需。一个字符串值。规定了替换文本或生成替换文本的函数。 |
大小写转换
toLowerCase() 和 toUpperCase。
字符串连接
concat() 方法用于连接两个或多个数组或者字符串。该方法不会改变现有的数组,而仅仅会 返回 被连接数组的一个副本。
1 |
|
返回值
返回一个新的数组。该数组是通过把所有 arrayX 参数添加到 arrayObject 中生成的。如果要进行 concat() 操作的参数是数组,那么添加的是数组中的元素,而不是数组。
1 |
|
去除首尾空格
在 JavaScript 中去除 字符串 的首尾空格,使用** trim 函数。有些浏览器不支持** trim 函数,那么我们可以自己通过replace函数实现 trim 函数。有的浏览器不支持trim函数,我们可以用repalce函数实现相同的效果
1 |
|
子串是否存在
可以使用字符串查找的方法,也可以使用includes方法,如果有则返回true,否则返回false。
1 |
|
参数为查找的子串和起始位置,位置可不写。
数组
JavaScript创建数组
JavaScript 的数组的创建有三种方法,即,使用 new 创建、使用 new 直接创建并实例化和隐式创建。
new
1 |
|
new创建并实例化
1 |
|
隐式创建
1 |
|
隐式创建并初始化
1 |
|
初始化数组
除了上部分的创建并初始化,还有几种初始化方式fill初始化
1 |
|
可以将item元素填充满数组
1 |
|
数组添加元素
向 JavaScript 的 数组 中添加元素有四种方法,即:直接使用 [] 添加元素、使用 push 添加元素、使用 unshift 添加元素和使用 splice 添加元素。
1 |
|
splic详解
JavaScript 的 splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。
1 |
|
数组删除元素
从 JavaScript 的 数组 中删除元素有七种方法,即:使用 length 属性删除、使用delete 删除、使用 pop 删除、使用 shift 删除、使用 splice 删除、使用迭代方式删除和使用 prototype 原型方法删除。
length删除
js的长度是可以修改的
1 |
|
delete
1 |
|
删除后长度不变,只是被赋值为undefined
pop
JavaScript 中的 Array 对象提供了一个 pop() 栈方法用于弹出并返回数组中的最后一项,某种程度上可以当做删除用。
栈数据结构的访问规则是 FILO(First In Last Out,先进后出),栈操作在栈顶添加项,从栈顶移除项,使用pop() 方法,它能移除数组中的最后一项并返回该项,并且数组的长度减 1
1 |
|
shift
JavaScript 中的 Array 对象提供了一个 shift() 队列方法用于弹出并返回数组中的第一项,某种程度上也可以当做删除用。
队列数据结构的访问规则是 FIFO(First In First Out,先进先出),队列在列表的末端添加项,从列表的前端移除项,使用 shift() 方法,它能够移除数组中的第一个项并返回该项,并且数组的长度减 1。
1 |
|
splic
在 JavaScript 的 Array 对象中提供了一个 splice() 方法用于对数组进行特定的操作。splice() 恐怕要算最强大的数组方法了,他的用法有很多种,在此只介绍删除数组元素的方法。
在删除数组元素的时候,它可以删除任意数量的项,只需要指定 2 个参数:要删除的第一项的位置和要删除的项数。
1 |
|
数组查找元素
使用 indexOf 方法、使用 lastIndexOf 方法、使用 findIndex 方法和使用 find 方法。前2者与string类似
findIndex
findIndex() 方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。
方法为元素调用函数(回调函数)
1 |
|
作为参数的函数至少要有一个形参:数组元素,另外两个可选参数为下标和数组本身,当函数返回true时,findIndex返回下标,并结束。
1 |
|
在findIndex中还有一个可选参数,“thisValue”,传递给回调函数的值一般用 “this” 值。如果这个参数为空, “undefined” 会传递给 “this” 值。
1 |
|
find
find和findIndex类似,但返回符合条件的第一个元素值,如果没有则返回undefined。
数组元素是否存在
和string类似,使用includes方法
数组长度
使用length属性
遍历数组
JavaScript 的 数组 的遍历方法有七种,即:使用 for循环 遍历、使用 foreach 遍历、使用 for in 遍历、使用 for of 遍历、使用 keys方法遍历、使用 values 方法遍历和使用 entries 方法遍历。
foreach
forEach方法会每个元素调用一次函数(回调函数),使用方法与find类似,也有thisValue参数可选,返回索引
1 |
|
for of
用法类似for in,但for in返回的是下标,for of返回值
1 |
|
map
JavaScript 的 数组 对象内置了 map 方法,可以用来遍历数组.用法类似forEach。为数组的每一个元素调用一个回调函数进行处理,处理完成后,将回调函数的返回值组成一个新的数组,若没有返回值则产生和原数组等长元素为undefined的数组
1 |
|
filter
JavaScript 的 数组 对象内置了 filter 方法,可以用来遍历数组,为数组的每一个元素调用一个回调函数进行处理,如果数组的元素符合回调函数的要求,那么会将该元素添加到新数组中。用法同上
1 |
|
every
用于检测数组中元素是否都符合条件,如果有一个不符合则返回false
1 |
|
some
JavaScript 的 数组 对象内置了 some 方法用于检测数组中的元素是否都符合指定条件,如果只要一个元素符合指定条件,则返回 true,所有元素都不符合要求,则返回 false。
同上
reduce
JavaScript 的 数组 对象内置了 reduce 方法用于接收一个 函数 作为累加器,将数组中的每个值(从左到右)开始缩减,最终计算为一个值。
1 |
|
参数 | 描述 |
---|---|
function(total,currentValue, index,arr) | 必须。数组每个元素需要执行的函数。 |
initialValue | 可选。传递给函数的初始值 |
参数 | 描述 |
---|---|
total | 必需。初始值, 或者计算结束后的返回值。 |
currentValue | 必需。当前元素 |
index | 可选。当前元素的索引 |
arr | 可选。当前元素所属的数组对象 |
1 |
|
这样就是将整个数组相加,1+2+3+4+5。而initiaValue可以设置初始值
1 |
|
代码运行
这样就是100+(1+2+3+4+5)
如果回调函数没有返回值,则每次调用都会将NaN返回
reduceRight
和reduce用法一样,不过reduceRight是从尾部开始
keys和values
JavaScript 的 数组 的 keys() 方法用于从数组创建一个包含数组键的可迭代对象,其中 keys 返回 的迭代器是数组的所有的索引,而不是数组的值。每个迭代器只能使用一次
1 |
|
JavaScript 的 数组 的 values() 方法用于从数组创建一个包含数组值的可迭代对象,其中 values 返回 的迭代器是数组的所有的值。
1 |
|
entire
JavaScript 的 数组 的 entries() 方法用于从数组创建一个包含数组键和值的可迭代对象,其中 entries 返回 的迭代器包含了数组的所有的键和值。
1 |
|
判断是否是数组
在 JavaScript 中,判断一个 变量 是否是 数组 使用 isArray 方法,如果是数组,则 isArray 返回 true,如果不是数组,则 返回 false。
1 |
|
1 |
|
数组合并
JavaScript 的 数组 的 concat() 方法用于将多个数组合并成一个数组,并 返回 合并后的数组。此方法并不会改变原来的数组,而仅仅是返回被连接的数组的一个副本。
1 |
|
数组转字符串
JavaScript 的 数组 的 toString() 方法 用于将数组转换为 字符串,同时,使用 toString() 方法将数组转成字符串时,数组的每个元素之间使用 “,” 分隔。
1 |
|
数组连接
JavaScript 的 数组 的 join() 方法用于将数组的所有元素连接成一个 字符串,同时,使用 join() 方法将数组连接成字符串时,还可以指定每个元素之间的分隔符。
数组拷贝
复制数组的一部分数据覆盖到数组的另一个位置。并返回数组,但是不会改变原数组的长度,会改变顺序。返回拷贝过后的数组。
1 |
|
参数 | 描述 |
---|---|
target | 必需。复制到指定目标索引位置。 |
start | 可选。元素复制的起始位置。 |
end | 可选。停止复制的索引位置 (默认为 array.length)。如果为负值,表示倒数。 |
1 |
|
数组填充fill
1 |
|
从字符串创建数组from
from() 方法用于通过拥有 length 属性的对象或可迭代的 对象 来 返回 一个数组。
1 |
|
参数 | 描述 |
---|---|
object | 必需,要转换为数组的对象。 |
mapFunction | 可选,数组中每个元素要调用的函数,返回值存入数组 |
thisValue | 可选,映射函数(mapFunction)中的 this 对象。 |
1 |
|
字符串反转
在 JavaScript 中,我们可以使用 reverse 函数,实现将 数组 的元素进行反转,reverse 函数会 返回 反转后的数组。
1 |
|
数组排序
在 JavaScript 中,我们可以使用 sort 函数,实现对 数组 的元素进行排序,sort 函数会修改原来的数组。
1 |
|
sortfunction指定排序顺序,必须是函数
1 |
|
面向对象
JavaScript对象特征
- 对象具有唯一标识性:即使完全相同的两个对象,也并非同一个对象。
- 对象有状态:对象具有状态,同一对象可能处于不同状态下。
- 对象具有行为:即对象的状态可能因为它的行为产生变迁。
- 在 JavaScript 中,将状态和行为统一抽象为 “属性”,考虑到 JavaScript 中将函数设计成一种特殊对象,所以 JavaScript 中的行为和状态都能用属性来抽象。
创建对象
在 JavaScript 中,创建一个 对象 有四种方法,即:通过 Object 方法创建、通过字面量方法创建、通过自定义函数(构造函数)创建 和 通过工厂模式创建。
Object方法创建
1 |
|
字面量创建
1 |
|
自定义函数方法创建对象(类)
1 |
|
1 |
|
对象属性
访问
使用.和[]访问对象属性
添加
访问后添加
删除
使用delete方法
1 |
|
遍历对象属性
在 JavaScript 中,遍历一个 对象 的所有 属性 有五种方法,即:使用 for in 遍历、使用 Object.keys 遍历、使用 Object.getOwnPropertyNames 遍历、使用 - Object.getOwnPropertySymbols 遍历和使用 Reflect.ownKeys 遍历。
- getOwnPropertyNames
在 JavaScript 中,遍历一个 对象 的 属性 可以使用 getOwnPropertyNames() 方法,Object.getOwnPropertyNames() 方法会返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性,这是和keys的区别,keys只包括可枚举类型)组成的 数组。1
Object.getOwnPropertyNames(obj);
1 |
|
- getOwnPropertySymbols
在 JavaScript 中,遍历一个 对象 的 属性 可以使用 getOwnPropertySymbols() 方法,Object.getOwnPropertySymbols() 方法会返回一个 数组,该数组包含了对象自身的所有 Symbol 属性的键名。
1 |
|
- ownKeys
在 JavaScript 中,遍历一个 对象 的 属性 可以使用 ownKeys() 方法,Reflect.ownKeys 返回一个 数组,该数组包含对象自身的所有键名,不管键名是 Symbol 或 字符串,也不管是否可枚举。1
Reflect.ownKeys(obj);
1 |
|
1 |
|
对象存在
在 JavaScript 中,判断一个 对象 是否有某个 属性 有三种方法,即:使用点或者中括号运算符、使用 in 语句和使用 hasOwnProperty 方法。
访问到不存在属性时,会返回undefined
in判断
1 |
|
如果对象 obj 中,含有属性 attr,那么 in 语句返回 true,否则,返回 false。
hasOwnProperty
1 |
|
hasOwnProperty 方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性(与in的区别),如果存在,则返回 true,否则,返回 false。
对象方法
在 JavaScript 中,方法是能够在 对象 上执行的动作。JavaScript 方法是包含函数定义的 属性。
this
面向对象语言中 this 表示当前 对象 的一个引用。但在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。
JavaScript this特点详解
- 函数在定义的时候 this 是不确定的,只有在调用的时候才可以确定。
- 一般函数直接执行,内部 this 指向全局 window,在严格模式下,this 是 undefined。
- 函数作为一个对象的方法,被该对象所调用,那么 this 指向的是该对象。
- 构造函数中的 this 其实是一个隐式对象,类似一个初始化的模型,所有方法和属性都挂载到了这个隐式对象身上,后续通过 new 关键字来调用,从而实现实例化。
new
在 JavaScript 中,new 运算符用于创建一个用户定义的 对象 类型的实例或具有构造函数的内置对象的实例。
instanceof
在 JavaScript 中,我们判断某个 变量 是什么 类型 的常常会用 typeof 运算符,但是使用 typeof 运算符不管引用的是什么类型的对象,它都返回的是 object 类型的。而instanceof 运算符可以查看具体的类型
1 |
|
参数 | 描述 |
---|---|
option | 是需要检测的对象。 |
constructor | 是你确定的对象,返回的是这个 option 是否属于 constructor 这个类型的布尔值。 |
构造函数
在 JavaScript 中,用 new 关键字来调用的 函数,称为构造函数。
在使用对象字面量创建一系列同一类型的对象时,这些对象可能具有一些相似的特征(属性)和行为(方法),此时会产生很多重复的代码,而使用构造函数就可以实现代码的复用。
JavaScript构造函数执行流程
- 当以 new 关键字调用时,会创建一个新的内存空间,标记为对象的实例。
- 函数体内部的 this 指向该内存。
- 执行函数体内的代码。
- 默认返回 this
值类型和引用类型
在 JavaScript 中 变量 的类型可以分为基本类型(也叫值类型)与复杂类型(也叫引用类型),其中,值类型就是 JavaScript 的基本数据类型,引用类型是复杂的对象类型。
值:字符串(string)、数值(number)、布尔值(boolean)、null、undefined。
引用类型:对象(Object)、数组(Array)、函数(Function)、日期(Date)、正则表达式(RegExp)。
值类型 | 引用类型 | |
---|---|---|
概念 | 原始值指的是原始类型的值,也叫基本类型 | 引用值指的是引用类型(类) 的值 |
数据类型 | 字符串(string)、数值(number)、布尔值(boolean)、null、undefined。 | 对象(Object)、数组(Array)、函数(Function)、日期(Date)、正则表达式(RegExp)。 |
存储 | 栈(stack),占内存空间固定,使用后被销毁 | 堆(heap),占内存空间不固定,使用后不一定被销毁,只有一个对象没有任何引用时,系统的垃圾回收机制才会回收销毁 |
赋值方式 | 1. 值的拷贝,创建一个新对象 2. 保存与复制的是值本身 3. 两份数据在内存中是完全独立的 |
1. 引用的拷贝,创建一个新引用 2. 保存与复制的是指向对象的一个指针 3. 变量中的存储的地址赋值一份单独存储, 两个变量中修改其中一个对象,另外一个引用来访问的时候,也会访问到修改后的值。 4. 使用 new() 方法构造出的对象是引用型。 |
作用域 | 函数作用域,在函数内部修改时生效,函数销毁时失效 | 函数中被修改时修改的是运行时数据区中的值,即使函数被销毁,变量的值依旧被改变。 |
比较方式 | 值的比较 | 引用的比较 |
参数传递 | 值类型按值传递 | 引用类型按引用传递 |
检测类型 | typeof 运算符 | instanceof 运算符在函数内部修改时生效,函数销毁时失效 |
原型
每一个 对象 (除 null 外)创建的时候,就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型中 “继承”属性。
prototype
在 JavaScript 中,每个 函数 都有一个 prototype 属性,这个属性指向函数的原型对象。
proto
每个对象(除 null 外)都会有的属性,叫做 __proto__,这个属性会指向该对象的原型。
每个原型都有一个 constructor 属性,指向该关联的构造函数。
原型链
在 JavaScript 中,每个继承父函数的子函数的对象都包含一个内部属性 _proto_。该属性包含一个指针,指向父函数的 prototype。
若父函数的原型对象的 proto 属性为再上一层函数,在此过程中就形成了原型链。
继承
JavaScript 中,实现继承有六种方法,即,分别为:使用原型链继承、借用构造函数继承、原型链+借用构造函数的组合继承、组合继承、 组合继承–优化版 以及 ES6 中 class 的继承。
原型链继承
1 |
|
我们通过将 Child的 prototype 设置为了 Parent,从而实现了继承。
原型链继承的主要问题是如果属性是引用类型,这个属性会被所有实例共享,如果修改了一个,其他实例的属性也会被修改,比如
1 |
|
构造函数继承
通过使用call
或apply
方法,可以在子类中执行父类型构造函数,从而实现继承。
1 |
|
构造函数继承无法继承原型链上的属性,只能继承父类构造函数内的属性和方法,优点是所有属性和方法,无论是否是引用类型,继承都是独立的
原型链和构造函数组合继承详解
组合继承将两种方式一起使用使得子类的原型属性(即父类构造函数内的属性)不会被共享,且可以继承父类原型链上的属性和方法
1 |
|
缺点:调用了两次Parent,在Child.prototype上添加了Parent的属性和方法
寄生组合继承
1 |
|
寄生组合继承只调用了一次Parent()
函数,但是**Child.prototype
的原始属性和方法会丢失**
class 的继承
1 |
|
Proxy对象
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
1 |
|
下面是handle
对象的方法
方法名 | 作用 |
---|---|
handler.getPrototypeOf() | Object.getPrototypeOf 方法的捕捉器,当读取代理对象的原型时,该方法就会被调用 |
handler.setPrototypeOf() | Object.setPrototypeOf 方法的捕捉器,主要用来拦截 Object.setPrototypeOf() |
handler.isExtensible() | Object.isExtensible 方法的捕捉器,用于拦截对对象的 Object.isExtensible()。 |
handler.preventExtensions() | Object.preventExtensions 方法的捕捉器,主要用来拦截 Object.preventExtension() |
handler.getOwnPropertyDescriptor() | Object.getOwnPropertyDescriptor 方法的捕捉器,方法是 Object.getOwnPropertyDescriptor()的钩子。 |
handler.defineProperty() | Object.defineProperty 方法的捕捉器,用于拦截对象的 Object.defineProperty()操作。 |
handler.has() | in 操作符的捕捉器 |
handler.get() | 属性读取操作的捕捉器 |
handler.set() | 属性设置操作的捕捉器 |
handler.deleteProperty() | delete 操作符的捕捉器 |
handler.ownKeys() | Object.getOwnPropertyNames 和 Object.getOwnPropertySymbols 方法的捕捉器 |
handler.apply() | 函数调用操作的捕捉器 |
handler.construct() | new 操作符的捕捉器 |
map映射
map和对象有点类似,都是以键值对的形式存储数据,他的使用方式如下:
1 |
|
接下来是对象和map的区别:
键的类型:
对象的键只能是字符串或symbol类型,而map接受所有类型,比如数组、数字、函数等
键的顺序:
在对象中,键的顺序并不是按顺序的,比如数字键会被提前,而map的键则是按照输入顺序
性能:
对象的属性查找性能通常在处理大量数据时较差,尤其是当键是非字符串类型时,浏览器和 JavaScript 引擎可能会执行额外的类型转换。
序列化:
对象可以直接与 JSON 进行序列化和反序列化。
JSON.stringify()
和JSON.parse()
支持对象的转换。Map
不能直接与 JSON 序列化工具一起使用。如果需要序列化Map
,需要先将其转换为数组。1
2
3
4
5
6
7
8
9// 对象序列化与反序列化
const obj = { a: 1, b: 2 };
const json = JSON.stringify(obj); // '{"a":1,"b":2}'
const parsed = JSON.parse(json); // { a: 1, b: 2 }
// map间接序列化
const map = new Map([['a', 1], ['b', 2]]);
const json = JSON.stringify([...map]); // '[["a",1],["b",2]]'
const parsed = new Map(JSON.parse(json)); // Map { 'a' => 1, 'b' => 2 }