js-基础总结1
JS中常用的数据类型
- 基本数据类型
- 数字number
- 包括常规数字和NaN
- 字符串string
- 布尔boolean
- 空对象指针null
- 未定义undefined
- Symbol
- 数字number
- 引用数据类型
- 对象数据类型object
- {} 普通对象
- [] 数组对象
- /^abc&/ 正则对象
- Math数学函数对象
- Date 日期对象
- ……
- 函数数据类型function
- 对象数据类型object
isNaN
NaN和任何值包括自己都不相等:NaN != NaN
检测一个值是否为有效数字,如果不是有效数字返回true,反之是有效数字返回false
在使用isNaN进行检测的时候,首先会验证检测的值是否为数字类型,如果不是,先基于Number() 这个方法,把值转换为数字类型,然后在检测,所以:
结论:isNaN发现是基本数据类型是用Number做隐式转换,引用数据类型先用toString转换在使用Number转换
console.log(isNaN(10)) // => false, 是有效数字
console.log(isNaN('10')) // => false, 是有效数字
console.log(isNaN('10a')) // => true, 不是有效数字
/* Number返回只能是number类型,number数字或NaN
* Number(5) => 5
* Number('10') => 10
* Number("") => 0
* Number('10A')=> NaN
* Number(true) => 1
* Number('AA') => NaN
* Number([]) => 0
* Number([1]) => 1
* Number([1,2])=> NaN
* Number({}) => NaN
*
*/
number类型
把其他类型值转化为数字类型
-
Number([val])
-
parseInt/parseFloat( [val], [进制] ): 也是转化为数字的方法, 对于有效字符串来讲,从左到右依次查找有效字符,直到遇到非有效数字字符,停止查找,(不管后面还有没有数字, 都不在查找了),把找到的数字返回
-
== 进行比较的时候,可能要出现把其他类型的值转化成字符串,如:'10' == 10 ,为true
-
四则运算除了加法,- * / 都能将字符串转化为数字类型
Number把字符串转换为数字,只要字符串中包含任意一个非有效字符串,结果都是NaN,空字符串会变成0
console.log(Number('12.5')) // => 12.5
console.log(Number('12.5px')) // => NaN
console.log(Number('12.5.5')) // => NaN, 第二个点.无法识别,不是有效数字
console.log(Number('')) // => 0
console.log(Number()) // => 0
console.log(Number(false)) // => 0
console.log(Number(true)) // => 1
// 所以
console.log(isNaN(false)) // false, 现将false转换为数字,Number(false),返回0,之后isNaN(0)返回false
console.log(Number(null)) // => 0
console.log(Number(undefined))// => NaN
// 把引用数据类型转化为数字, 是先把它基于toString方法转化为字符串,然后在转化为数字
console.log(Number({name:'cyj'})) // => NaN
console.log(Number({})) // => NaN
// 执行toString() "[object object]"
console.log(Number([])) // => 0
// [].toString => ""
console.log(Number([12])) // => 12
console.log(Number([12,35])) // NaN
结论:
(1). Number在转换基本数据类型的时候,需要注意的是,
1.false返回0
2.null返回0
3.undefined返回NaN
4.""返回0
检测false返回0,true返回1,""返回0,null返回0,undefined返回NaN
(2). Number在转换引用数据类型的时候,需要注意的是,会先调用toString方法,在检测是否为数字,
如:
1.{}返回NaN,因为{}.toString()返回"[object object]"
2.[]返回0,因为[].tostring()返回"",Number("")返回0
3.[1]返回1,因为[].toString()返回字符串"1",Number("1")返回数字1
4.[1,2]返回NaN,因为[1,2].toString()返回"1,2",Number("1,2")返回NaN
// parseInt/parseFloat([val],[进制])
let str = '12.5px'
parseInt(str) // => 12
parseFloat(str) // => 12.5
parseFloat('a12.5') // => NaN
parseFloat('width:12px') // => NaN
string 字符串类型
所有用单引号、双引号、反引号都是字符串
把其他类型值转化为字符串
- [val].toString()
- 字符串拼接
// [val].toString()
let a = 12
console.log(a.toString()) // => '12'
console.log((12)).toString()) // => '12'
console.log((NaN).toString()) // => 'NaN'
// null和undefined是禁止直接toString的
console.log((null).toString()) // 报错
console.log((undefined).toString()) // 报错
// 但是转化为字符串的结果就是 'null/undefined',只不过浏览器不让这么用
console.log([].toString()) // => ""
console.log([12,123].toString()) // => "12,123"
console.log(['12','123'].toString()) // => "12,123"
// 基本上所有的值toString()之后都是在头上添加引号包起来,但是只有一个例外
({}.toString()) // [object object]
({name:"ctyj"}.toString()) // => [oject object]
// 普通对象.toString()结果都是 "[oject object]"
// Object.prototype.toString方法不是转换为字符串,而是用来检测数据类型的
// 字符串拼接
// 四则运算法则中,除加法外,其余都是数学运算,只有加法可能存在字符串拼接
console.log('10' + 10) // => 字符串 1010
console.log('10' - 10) // => 数字 0
console.log('10px' - 10) // => NaN -10 => 返回NaN
let a = 10 + null + true + [] + undefined + '之风' + null + [] + 10 + false
11undefined之风null10false
基本数据类型转化为字符串调用Number(), 而复杂数据类型转化为字符串调用.toString()
boolean布尔类型
只有两个值 true/false
把其他类型值转化为布尔类型
只有 0 、NaN、""、undefined、null转化为false,其余都是true,而且没有任何的特殊情况
- Boolean([val])
- !/!!
- 条件判断
//
if('123px' - 123){
console.log('haha')
}
null 和 undefined
-
null:意料之中(一般都是开始不知道值,手动先设置为null,后期在赋值)
-
let num = null // let num = 0; 一般是用null,因为0不是空值,它在栈内存里面有自己的存储空间 num = 12
-
-
undefined:意料之外
-
let num; console.log(num) // => undefined // 创建变量不赋值,默认就是undefined
-
object对象数据类型
{[key]:[value],...} 任何一个对象都是0到多组键值对(属性名:属性值),切属性名/键不能重复
对象是什么:描述一个对象的特征
let person = {
name:'cyj',
age:22,
height: '180CM',
weight: '65KG',
1:100
}
console.log(person.name) // => cyj
console.log(person['name']) // => cyj
const str = 'height'
console.log(person[str]) // => 180CM
// 删除属性
// => 真删除:把属性彻底干掉
delete person[1]
// => 假删除:属性还在,值为空
person.weight = null
console.log(person)
看一看数组这个特殊的对象数据类型
- 为什么数组是特殊的对象:
- 1.我们在中括号中设置的是属性值,它的属性名是默认生成的数组,从0开始递增,我们将这个属性名称为索引
- 2.天生默认一个属性名 length,存储数组的长度
javascript堆栈
浏览器想要执行JS代码:
1.从电脑内存中分配出一块内存,用来执行代码(栈内存 => Stack)
2.浏览器分配一个主线程用来自上而下执行js代码
基本类型:按值操作(是直接操作值),所以也叫值类型
引用类型:操作的是堆内存的地址(是按引用地址操作的),所以也叫引用类型
先来一道阿里面试开胃题
let a = {
n:1
}
let b = a
a.x = a = {
n:2
}
console.log(a.x)
console.log(b)
JS中数据类型的检查
- typeof [ val ] : 用来检测数据类型的运算符
- instanceof:用来检测当前实例是否属于某个类
- constructor:基于构造函数检测数据类型(也是基于类的方式)
- Object.prototype.toString().call:检测数据类型最好的方法
typeof 局限性
基于typeof检测出来的结果
- 首先是一个字符串
- 字符串里面包含对应的类型
局限性:
let fn = () => {
return '特殊'
}
typeof null // => "object"
typeof undefined // => "undefined"
typeof {} // => "object"
typeof [] // => "object"
typeof /^/ // => "object"
typeof fn // => "function"
基于typeof无法细分当前的值是普通对象还是数组对象,因为只要是对象数据类型,返回的结果都是object
但是有两点除外比较特殊
- typeof null 返回object,null是基本数据类型,但是typeof把null当成空对象指针返回object
- typeof fn 返回function,function是引用数据类型,但是typeof能分辨函数对象数据类型
结论:typeof 只能检测基本数据类型,基本数据类型里面null特殊,返回object,引用数据类型function特殊,返回不是object而是function。
JS中的操作语句:循环、判断
continue:结束当前这轮循环(continue后面的代码不再执行),继续执行下一轮循环
break:强制结束整个循环
浏览器内核
webkit内核(v8引擎)
+ 谷歌Chrome
+ Safari
+ Opera ≥ V14
Gecko
+ 火狐Firefox
Presto
+ Opera ≤ V14
Trident
+ IE
+ IE EDGE 开始采用双内核(包含chrome)
let i ='10'
i++
i等于数字11
函数
arguments : 函数内置的实参集合
- 类数组集合,集合中存储着所有函数执行的时候,传递的实参信息
- 无论是否设置形参,arguments都存在
- 无论是否传递实参,arguments都存在
arrow function 箭头函数
箭头函数没有arguments,但有一个更好用的...arg
let sum = (...arge) = > {
console.log(arge)
}
sum(1,2,3,4)
结论:arguments是类数组,也叫伪数组,无法调用数组的方法,但是es6的箭头函数,arge是一个真的数组,拥有数组的方法。
注:将伪数组转换成数组的方法
-
结构
-
let arr = null function fn(){ arr = arguments } fn(1,2,3) let newArr = [...arr]
-
-
Array.from
-
let arr = null function fn(){ arr = arguments } fn(1,2,3) let newArr = Array.from(arr)
-
-
使用Array原型上slice和call
-
let arr = null function fn(){ arr = arguments } fn(1,2,3) let newArr = Array.prototype.slice.call(arr) // 或则 newArr = [].slice.call(arr)
-
-
使用for循环遍历
-
let arr = null funciton fn(){ arr = arguments } fn(1,2,3) let newArr = null for(let i = 0 ;i < arr.length ; i++){ newArr[i] = arr[i] }
-
Math
数学函数:但它不是一个函数,它是一个对象,对象中国呢存储了很多操作数字的属性方法,因此被称为数学函数。
- Math.abs([number value]) => 获取绝对值
- Math.ceil([number value]) => 向上取整
- Math.ceil(12.1) => 13
- Math.ceil(-12.9) => -12
- Math.ceil(-12.1) => -12
- Math.floor([number value]) => 向下取整
- Math.floor(12.1) => 12
- Math.floor(12.9) => 12
- Math.floor(-12.9) => -13
- Math.floor(-12.1) => -13
- Math.round([number value]) => 四舍五入
- Math.round(13.3)
- Math.max / Math.min
- Math.sqrt / pow()
- sqrt:给一个数开平方 Math.sqrt(4) => 2
- pow: 计算一个数的多少次幂 Math.pow( 需要计算的数,这个数的幂是多少 )
- Math.pow(2,3) => 8
- Math.pow(2,4) => 16
- Math.random() => 随机获取0到1之间的数
- Math.random() * n => 获取0到n之间的数
- 获得n到m之间的随机数 包含n也包含m
- Marth.floor(Math.random() * (m-n + 1) + n)
- Math.round(Math.random() * ( m - n ) + n )
数组及数组中常用的方法
- 方法的作用隔阂含义
- 方法的实参( 类型和含义 )
- 方法的返回值
- 原来的数珠是不是会发生改变
1.实现数组增删改的方法
这一部分方法都会修改原有的数组
push
: 向末尾添加内容@params :参数
多个任意类型
@return : 返回值
新增后数组的长度
unshift
: 向头部添加内容@params
多个任意类型
@reutrn
数组的长度
shift
: 删除数组的第一项,返回值是删除的第一项delete arr[i] => 将数组的第i项删除,但是数组长度不改变,empty
pop
: 删除数组最后一项,返回值是删除的最后一项也能使用 arr.length--,删除最后一项
splice 实现数组的增加删除修改
splice
@params
n,m 数字, 从索引n开始,删除m个元素
@return
把删除的部分,用新数组返回
let arr = [1,2,3,4,5] arr.splice(0) // => 类似数组的克隆,但是有副作用,将原数组清空了修改了
@params
n,m,x从索引n开始删除m个元素,用x占用删除的部分
n,0,x从索引n开始删除0个,把x放在索引n这个位置
2.数组的查询和拼接
这一组的方法,不会修改原数组
slice
@parmas
n,m 从索引n开始,找到索引为m的地方( 不包含m这一项 )
@return
把找到的内容以新数组形式返回
let arr = [1,2,3,4,5] let newArr = arr.slice(0) // 数组的克隆/拷贝 => 没有副作用
concat
: 实现数组的拼接@params
多个任意值类型
@return
拼接后的新数组( 原来的数组不变 )
let arr1 = [1,2,3] let arr2 = [4,5,6] arr1.concat(arr2,7,8,9)
3. 把数组转化为字符串
原有数组不变
toString
@params
@return
转化后的字符串( 原来数组不变 )
let arr = [1,2,3,4,5] arr.toString() => "1,2,3,4,5" console.log([].toString()) // => "" console.log([12].toString()) // => "12" console.log([12,13].toString()) // => "12,13" 有多项时,每一项逗号分隔
join
@params
指定的分隔符( 字符串格式 )
@return
转化后的字符串( 原来数组不变 )
let arr = [1,2,3,4,5] console.log(arr.join()) // => "1,2,3,4,5" console.log(arr.join("")) // => "12345" console.log(arr.join("+")) // => "1+2+3+4+5" console.log(eval(arr.join("+")))// => 15 // eval 就是把字符串变成JS表达式执行 所以数组求和相乘相减之类的就能使用: let result = eval(arr.join("+"))
4. 检测数组中是否包含某一项
indexOf /lastIndexOf
indexOf
: 检测当前项在数组中第一次或最后一出现的索引值@params
要检测的内容
@return
这一项出现的索引位置,如果没有查到,返回-1
es6新语法
includes
@params
要检测的内容
@return
返回值为Boolean,true | false
let arr = [1,2,3] arr.includes(1) // => true
5. 数组的排序或者排列
reverse
reverse会修改原数组,将元素倒叙排列
@params
@return
排序后的新数组
let arr = [1,2,3,4,5] arr.reverse() // => [5,4,3,2,1] 将数组倒过来,修改了原数组
sort
@params
参数可以没有,也可以是一个函数
@return
排序后的新数组
原数组改变
let arr = [2,5,3,1,4] arr.sort() // => [1,2,3,4,5] 默认后小到大排序 let arr1 = [21,1,32,5,12,53] arr.sort() // => 如果sort不传递参数,默认是无法处理10以上的排序 arr.sort((a, b) => { return a - b }) // a - b 升序排列 arr.sort((a, b) => { return b - a }) // b - a 降序排列
5. 数组遍历的方法
forEach
@params
回调函数
@return
无
let arr = [1,2,3,4,5] arr.forEach((item,index) => { console.log(item,index) // return 在forEach里面没有作用,并不会跳出循环,并且使用break会报错 })
map
@params
回调函数
@return
当有return的时候返回一个新的函数
let arr = [1,2,3,4,5] let newArr = arr.map(item => { return item + 1 }) console.log(newArr) // => [2,3,4,5,6]
数组去重
// 算法思路 // 1. 创建一个新的数组,遍历原数组,判断原数组当前这一项在新数组是否存在,不存在就放进去,存在什么都不做 let arr = [1,3,2,5,1,2,4,2,3,1,5,1] let newArr = [] arr.forEach(item => { if(!newArr.includes(item)){ // 说明newArr里面不存在这个数 newArr.push(item) } }) // 方案2 // 1. 不创建新的函数,遍历数组,判断当前遍历的这一项在后面是否存在,存在就移除后面的那一项,如果还有继续移除 for(let i = 0 ; i < arr.length ; i++){ let item = arr[i] for(let j = i+1 ; j < arr.length ; j++){ let compare = arr[j] if(compare === item){ arr.splice(j,1) j-- } } } // 方案3 let obj = {} arr.forEach((item,index) => { // 判断obj里面是否存在这个key,存在值+1,不存在初始化,value=0 if(!obj[item]){ obj[item] = 1 }else{ obj[item] += 1 } }) // 方案4 arr.sort((a, b) => a - b) let str = arr.join("@") + "@" let reg = /(\d+@)\1+*/g let newArr = [] str.replace(reg,(n,m) => { m = Number(m.slice(0,m.length - 1)) newArr.push(m) }) // 方案5 let arr = [1,2,1,2,3,1,2,3,1,2,1,3,1] arr = [...new Set(arr)] // 完成去重
字符串中常用的方法
1. 获取字符
charAt / charCodeAt
charAt
charAt等用与 str[...]
let str = 'helloworld' charAt(0) // => h str[0] // => h 而charCodeAt是获取指定字符的ASII码中10进制的编码值(Unicode编码值) 'a'.charCodeAt() // => 97 charCodeAt(0) // => h 的ASII码值 => 104 console.log(String.fromCharCode(97)) // => a
2. 字符串的截取
substr / substring / slice
实现字符串截取的3个方法, 截取,不会修改原字符串
substr
(索引,个数)@params
n,m 从索引n开始截取n个字符,m不写截取到末尾(后面的方法也是)
substring
(索引,索引)@params
n,m 从索引n开始截取到索引m, 不包括m
slice
@params
n,m 和substring一样,都是找到索引为m处,但是slice可以支持索引为负数,其余两个方法是不可以的
let str = 'zhufengpeixun'
str.substr(3,4) // => "feng"
str.substring(3,4) // => "f"
3. 大小写
toUpperCase / toLowerCase
4. split
**split([分隔符]) :把字符串按照指定的分隔符拆分成数组 **(和数组的join() 相对应 )
split支持传递正则表达式
let str = "music|movie|sport|dancing|swimming"
str.split("|")
split
@params
分隔符
@return
数组
5. replace
replace(新字符,老字符):实现字符串的替换
let str = "@qwe@eqr@q@e@5@4"
str.replace("@","!") // => 默认只替换一次
str.replace(/@/g,"!") // => 配合正则全部替换
获取DOM元素的方法
- document.getElementById() // 获取id的这个对象
- document.getElementsByTagName() // 通过标签名获取一组元素的集合
- document.getElementsByClassName() // 通过样式类名获取一组元素的集合
- document.getElementsByName() // 在整个文档中,通过标签的NAME属性获取组节点集合
- document.head / document.body / document.documentElement获取 HEADER / BODY / HTML元素
数组的splice方法:splice(n,m,x)
从下标n开始,删除m个,将删除的替换为x
当m为0时,下标n开始,添加x
数组的slice个字符串的substring一样,slice(n,m) substring(n,m)
都是从下标n开始截取到下标m
而字符串的substr不一样,从下标n开始截取m个