js
基本要求:
window.onload:先加载,最后执行:
浏览器默认是从上往下执行代码的
因为我的js代码一般都要写到最后,script写在body的最后面,但是我想写在head的话,我就需要使用window.onload给他包裹起来,当所有的加载都完毕的时候,执行包裹的代码。
这个和vue3中的生命周期钩子,onMounted类似,都是加载完成后在进行。
对于弹窗:
1 | console.log()//用于调试 |
网页内容输入:
document.write()
常量和变量:
ES6新增:const和let,其中const为常量,let为变量
而在之前还有var,现在不用了。
- 可以先使用在声明,存在变量提升,仅仅是不用声明了,但是依旧是没有赋值的,此时打印仍为undefined,只是不报错罢了。
- 没有块级作用域,要么是全局要么是整个函数(不会被if、for{}给包起来)
对于const、let,同时变量声明是有顺序的,后面的值会把前面的给覆盖掉。
对于const为常量的理解:不可变的是指针内存地址,而不是对象内部的数据
例如const arr = [],你可以通过数组的push方法进行修改里面的内容,但是不能让arr = [1]指向一个新的数组
基本数据类型:
引用数据类型只有一种,那就是Object
- 对象属性: 你可以随意给它添加
name,age等属性。 - 动态性: 因为是值传递,可以在运行时随时增删改内容。
- 共享性: 多个变量可以指向同一个内存空间,修改的只是值。
栈内存和堆内存:
栈内存是对于数据进行操作,而我的堆内存是对于内存地址进行操作,速度慢一些。
字符串:string
转义字符:
\'表示'单引号\"表示"双引号\\表示\\r表示回车\n表示换行。n 的意思是 newline。\t表示缩进。t 的意思是 tab,制表符。\b表示空格。b 的意思是 blank。
这些的作用就是,因为都是字符串类型,需要使用引号,会与我的引号重复,所以说需要使用特殊的字符来代替我所想要表达的意思。
字符串拼接:
用**+(更加偏向隐式转化为字符串类型),而别的运算符更加偏向转为number**
当使用拼接的时候,会自动把数据类型转换为字符串类型。
隐式转换:
-、*、/、%这几个符号会自动进行隐式转换,是将字符串类型自动转换为数字类型。(记住没有+)
对于+来说,字符串的拼接是最优先的。
模板字符串:(很常用)
1 | var name = 'qianguyihao'; |
数值型:Number:
- 不分家: JS 不分
int,float,double,统一都是Number(底层是 64 位浮点数)。 - 有陷阱: 小数运算不精准(如
0.1 + 0.2 != 0.3),因为二进制存储时会产生舍入误差(计算机都是二进制,就像十进制1/3=0.33333…..一样,二进制也无法处理小数,会产生误差)。 - 避坑指南: > 当涉及小数计算,先乘 10 的倍数化为整数,算完再除回去。例如:(0.1× 10 + 0.2 × 10) / 10 = 0.3
- 或者使用
toFixed(n)保留几位小数(注意:返回的是字符串)。
- 或者使用
连字符和加号的区别:
如果+两边都是数字,那么就是加号,否则就是连字符。
对于Undefined和null:
更常用的是Underfined,null只是一个用来定义空对象的。
在进行计算的时候,underfine和任何进行计算都是NaN,而null可以当成0来计算。
数据类型的转化:
显式类型转换:
- toString()
- String()
- Number()
- parseInt(string)
- parseFloat(string)
- Boolean()
隐式类型转换:
- isNaN() 函数
- 自增/自减运算符:
++、—- - 运算符:正号
+a、负号-a - 运算符:加号
+ - 运算符:
-、*、/、% - 比较运算符:
<、>、<=、>=、==等。比较运算符的运算结果都是布尔值:要么是 true,要么是 false。 - 逻辑运算符:
&&、||、!。非布尔值进行与或运算时,会先将其转换为布尔值,然后再运算。&&、||的运算结果是原值,!的运算结果为布尔值。
隐式类型转换实际上还是调用显示转换的方法。
转换为String:
- 调用tostring方法:
该方法不会影响到原变量,但是对于null和undefined是无法转换的,会报错。
1 | let a1 = 123; |
对于进制来说(二进制等),只是表现形式,但是对于计算机来说,所有的表现形式实质上都是字符串。
- 调用string方法:
它和tostring方法不一样的就是,更加安全,即就是对于null和undefined来说,不会报错。
对于其他本质上就是在调用tostring,而对于特殊的:将 undefined 直接转换为 “undefined”,将 null 直接转换为 “null”。
转换为Number:
使用number()函数
| 原始值 | 转换后的值 |
|---|---|
| 字符串 | (1)字符串去掉首尾空格后,剩余字符串的内容如果是纯数字,则直接将其转换为数字。 (2)字符串去掉首尾空格后,剩余字符串包的内容只要含了其他非数字的内容(小数点按数字来算),则转换为 NaN。怎么理解这里的 NaN 呢?可以这样理解,使用 Number() 函数之后,如果无法转换为数字,就会转换为 NaN。 (3)如果字符串是一个空串或者是一个全是空格的字符串,则转换为 0。 |
| 布尔值 | true 转成 1;false 转成 0 |
| undefined | NaN |
| null | 0 |
parseInt:
- parseInt()/parseFloat() :提取出最前面的数字部分(开头如果是空格,则自动忽略空格);没提取出来,那就返回 NaN。
注意不是四舍五入保留整数,而是直接截断整数,例如5.8直接变成5
有包含进制转化的功能:
1 | var a = '110'; |
隐式转换类型:
- boolean + 数字 = 数字
boolean 型和数字型相加时, true 按 1 来算 ,false 按 0 来算。这里其实是先调 Number() 函数,将 Boolean 类型转为 Number 类型,然后再和 数字相加。
- null + 数字 = 数字
等价于:0 + 数字
- undefined + 数字 = NaN
计算结果:NaN
- 任何值和 NaN 运算的结果都是 NaN。
转换为布尔:
空串和全是空格的字符串含义不同:
其中空串为:’’ “”
而全是空格的字符串:’ ‘
就是这个意思
使用 !!
使用 !!可以显式转换为 Boolean 类型。比如 !!3的结果是 true。
运算符:
幂运算:
ES6新增语法,**即就是:
1 | 2**3; |
浮点数:
- 不要直接比较两个浮点数的大小,肯定不对
- 对于涉及金钱的数据处理交给后端
- 因为计算机表示都是用二进制来表示的,无法精确表示浮点数,修改规则的话成本会非常高。
自加运算符:
对于这种运算符来说,不能对常量和表达式使用,只能操作变量。
typeof:
1 | typeof 数字(含 typeof NaN)//结果为number |
非布尔值的与或运算【重要】:
1 | //&&它就是且的意思,全真才能为真 |
- 对于三元运算符:其中&&就是从前往后找第一个fasle,如果找不到的话就返回最后一个。
- 对于||从前往后找第一个true,如果找不到就返回最后一个。
===和==区别:
==会做隐式类型转换
===则不做类型转换。
‘6’和6,是不等的,一个是字符串,一个是数字本身。
单目运算符和双目运算符:
就比如+来说:
单目:只有一个操作符,i++
双目:多个,a+b
break和continue:
break语句:
- 可以用来退出switch语句或者整个循环语句(while、for循环)
- break会立即终止离他最近的循环语句
- label的使用:可以指定跳转循环
1 | const matrix = [ |
continue语句:
break是退出所有循环,而continue是退出当前循环
其余的性质都是通用的。
循环来说:
打印99乘法表,在输出的时候第二个循环参数在前,如果需要整齐,需要设置一个span标签,并且给其设置inline-block属性,如果需要在块级元素中居中,text-align:center;因为不同数字大小是不同的,所以说可以统一规格,每个块的大小是一样的,完全能容纳乘法元素
其中block是独占一行,不管内容有多少都是独占一行
但是inline-block,是排满一行才会换行。
内置对象:
创建对象:let obj1 = new Object();
属性和方法只能添加给对象,不能添加给基本数据类型。
基本包装类型:
在底层是以字符串数组的形式保存的,因此既可以获得字符串长度,也可以根据index索引获取单个位置的元素,就像操作数组一样。
1 | let str = 'smyhvae'; |
string字符串的常见方法:
- 查找字符串:indexOf()从前往后遍历
- lastIndexOf()从后往前遍历
- 查询结果为-1说明没找到
1 | 索引值 = str.indexOf(想要查询的字符串, [起始位置]); |
endsWith和startsWith:
这俩的起始索引不一样
1 | // 因为指定了起始位置为3,所以是在 defg 这个字符串中检索。 |
获取指定位置字符串:(str.通过.操作符进行访问)
- charAt(index) (老代码的维护)
- str[index](最常用)
- charCodeAt(index)
- 返回指定字符串的Unicode编码,不会修改原字符串。(a是97,A是65)
字符串截取:
(2, 5)截取时,包左不包右。(2)表示从指定的索引位置开始,截取到最后。(-3)表示从倒数第三个开始,截取到最后。(1, -1)表示从第一个截取到倒数第一个。(对于hello来说,截取的是ell)
特殊在于如果前面的值大于后面,直接返回空字符串。
其余和slice方法一样
特殊的就是,不能接受负值,如果传递的是负值,默认使用0。
如果第二个参数小于第一个参数,比如说, substring(1, 0)相当于截取的是第一个字符。(注意substring会把所有的负数当作NaN处理,也就不存在substring(1, -2)这种交换方法)
和slice不同,可以自作聪明,如果后面的数字大于前面的话,会进行自动交换。
split():字符串转换为数组(很重要)
通过指定分隔符,将字符串拆分成一个数组。不会改变原字符串。
split()无参数,就是将一整个字符串添加到数组中。
split(‘’),把每一个字符添加到数组中
其余就是在’’加指定字符进行分割。
注意:在切割的时候,如果是切割的是两个数字中间的数,会返回两个值,但是呢,如果右边没有值的话,我会返回一个空字符串。
1 | // 例子 1:标准分割 |
replace():
(返回的是一个新的字符串,旧的不需要接受) = str.replace(被替换的子串,新的子串);
只能替换第一个字符串,如果要替换所有的字符串,需要使用正则表达式
1 | let str = "苹果红了,苹果甜了,苹果熟了"; |
正则表达式:
1 | let str = "apple, apple, apple"; |
replaceAll();(比正则表达式简单一些)
1 | let str = "apple, apple, apple"; |
repeat():
重复字符串,可以用来模糊处理电话号码的后四位
1 | const telephone = '13088889999'; |
大小写转换:
1 | let str = 'abcdEFG'; |
几个疑惑点解答:
1 | let a = {}//定义的是一个对象 |
内置数学函数:
1 | Math.abs()//绝对值,可以对传进来的字符串进行隐式转换 |
Date()对象:
一定要注意,月份和日期是从0开始的
| 方法名 | 含义 | 备注 |
|---|---|---|
| getFullYear() | 获取年份 | |
| getMonth() | 获取月: 0-11 | 0代表一月 |
| getDate() | 获取日:1-31 | 获取的是几号 |
| getDay() | 获取星期:0-6 | 0代表周日,1代表周一 |
| getHours() | 获取小时:0-23 | |
| getMinutes() | 获取分钟:0-59 | |
| getSeconds() | 获取秒:0-59 | |
| getMilliseconds() | 获取毫秒 | 1s = 1000ms |
1 | const now = new Date(); |
数组:
数组解构:
1 | let [a, b, c] = [1, 2, [3, 4]]; |
数组元素的删除和添加:
push():向数组的最后插入一个或多个元素,返回结果为新数组的长度。会改变原数组,因为原数组变成了新数组。(返回的是新长度)
1 | var arr = ['王一', '王二', '王三']; |
pop():删除数组中的最后一个元素,返回结果为被删除的元素。(返回的是被弹出删除的数字)
1 | var arr = ['王一', '王二', '王三']; |
将伪数组转换为真数组:
Array.from(lis,callback),第二个参数是回调函数
const result = Array.from(lis, item => Number(item.innerText)).reverse();
- 什么是伪数组:有索引值0,1,可以获取长度length,但是不能调用有关数组的方法。
1 | function sum() { |
- 还有网页dom元素也是也是伪数组
1 | // 获取的是伪数组 NodeList |
indexOf() 和 lastIndexOf():获取元素的索引:
indexOf()在检索时,是严格类型约束,类似于===。
也就是说不会进行隐式转换
1 | let arr = ['1', '2', '3', '4', '5']; |
forEach(item,index,arr):
回调函数中传递三个参数:
- 参数1:当前正在遍历的元素
- 参数2:当前正在遍历的元素的索引
- 参数3:正在遍历的数组
数组是引用数据类型,存储的是地址,与基本数据类型不一样,如果你直接修改对应值的话,地址不变,那么你是无法修改的,但是你可以通过.操作符对对象中的某一项进行修改,修改的是地址值,数值会发生改变。
如果我想修改数组中的值,那么就要进行index索引进行赋值
1.
1 | //在原有的数据上进行操作 |

1.
1 | const object = [ |

1.
1 | const obj = [ |

map集合:
是可以返回一个新的数组,可以对返回的值进行链式调用。
- map一定要写return(但是箭头函数可以简写在一行的时候就可以省略这个return),或者用一个新的参数来接收,如果没有return那么就返回undefined。
1 | const salary = [4000, 7000, 3000, 5000]; |
filter:
返回的是布尔值,从数组中筛选出来满足条件的值进行返回
return语句也就代表着选择的结束,要注意循环的位置,如果是在if-else语句中,那么就可以起到筛选的作用,满足条件的return出去,不满足条件的接着执行代码。
Splice:
使用splice删除数组的时候,因为js是紧密数组,当我删除一个元素的时候,其余元素会进行补位,如果不进行补位的话,那么删除的元素会变成undefined,那么我在删除数组的时候可能会漏掉一些。
1 | let arr = [1, 2, 2, 3]; |
函数:
形参和实参:
形式参数:不是真的参数,只是代表我的接受我传递的实际参数。
实参:就是我的传值
注意他们的个数问题,最好是要一样。
如果实参个数小,没有影响,即就是我的多余实参没有传值进入罢了。
但是一旦形参少了,没有接收到的值会变成undefined,那么在运算的时候结果会变成NaN。
对于…操作符:
- 在形参里叫“剩余参数”:负责打包。把散装的参数收纳成一个真数组。
1 | console.log(...[1, 2, 3]) |
- 在实参里叫“展开运算符”:负责拆散。把数组拆开成散装的参数。
优势:彻底取代 arguments。
- 支持箭头函数。
- 原生就是真数组,直接链式调用
map/filter/reduce。
1 | function sum(...args) { |
立即执行函数:
1 | var arr = []; |
- 当我使用立即执行函数
1 | var arr = []; |
this指向:
其中call和apply是立即执行的,bind需要调用才能执行
call():
call() 方法的作用:可以调用一个函数,与此同时,它还可以改变这个函数内部的 this 指向。
call() 方法的另一个应用:可以实现继承。之所以能实现继承,其实是利用了上面的作用。
1 | //语法 |
apply() 方法
需要传递数组,apply是一个拆箱的过程,是将数组拆成一个一个的数字
1 | //语法 |
bind() 方法
不会立即执行,返回的是一个函数,我必须要调用才行。
1 | const person = { |
闭包:(内部函数+所引用的外部变量)
闭包是为了解决全局变量数据,会被修改,进行数据的私有化。(执行完变量并不会被释放,所以会造成内存泄露,可以手动释放赋值null即可)
1 | function createCheckTemp(standardTemp) { |
深拷贝和浅拷贝:
浅拷贝:(只赋值第一层属性,如果是基本数据类型,是值传递,如果是引用数据类型就是址传递,即就是内存地址)
Object.assgin() 方法用的最多:
1 | // 语法1 |
- 其中浅拷贝的方法:
1 | const myObj = { |
很重要!
1 | const obj1 = { |
深拷贝:
structuredClone(obj2, obj1);
在深拷贝中,如果我修改obj2的值,不会影响obj1里面的值。
- 总结:
遇简单类型则“赋值”:因为基本数据类型在内存中是按值传递的,改一个不会影响另一个。
遇复杂类型则“开辟新空间并递归”:这是为了打破“引用关系”。而复杂数据类型是按照址传递的。
jQurey:
- 其中$是一个函数,和jQuery是等价的(为了解决不同浏览器的获取元素方法不同的问题)

let,var,const:
- let和const是ES6新增的
- var是一个全局变量,而let和const是一个块级变量,主要体现在for循环中(解决办法可以用立即执行函数和let块级作用域声明)
1 |
|
暂时性死区:
对于let和const,强制先声明后使用。
解构赋值:
let [a, b, c] = [1, 2, 3];
对于解构赋值,如果在左边都有默认值的情况下,赋值undefined,仍为默认值,而赋值null,那么就会null
1 | { |
…操作符:
- 剩余参数:是用来接收的,剩余元素放到一个数组中的
- 扩展运算符:浅拷贝(保证第一层数据会指向一个新的内存地址),不随原来数据的改变而改变。
- 将数组拆成一个个的字符串。
如果我想在一个对象中放入另一个对象,直接操作是不行的,这个时候我就需要用…操作符进行解构然后赋值,即就是:
1 | const baseInfo = { name: '张三', age: 25 }; |
参考资料
- qianguyihao: https://github.com/qianguyihao
- Web 教程: https://github.com/qianguyihao/Web
