js中的数据类型分类
基本数据类型:由简单的结构组成的
● 数字(number)
● 字符串(string)
● 布尔(boolean)
● null
● undefined
引用数据类型 : 结构相对复杂一些
● 对象数据类型(object) 数组属于对象属性类型 ,所以数组也属于引用数据类型
● 函数数据类型(function)
Number
//细节点
Number() //强制转为number类型 如有带有文字 就会返回NaN
parseInt() // 强制转为number类型 把数字返回,遇到文字就停止 ,如果第一个就是文字,返回NaN
parseFloat() //比parseInt多判断一个 .
Boolean
数据类型转换的规则:
● 如果只有一个值,判断这个值是真还是假,遵循:
只有 0 NaN ''(空字符串) null undefined 这五个是假的,其余都是真
// !:一个叹号是取反,首先将值转化为布尔类型的,然后再取反
console.log(!3) //false 先把3转为boolean , 然后再取反 3转为布尔类型就是 true 取反就变为 false
console.log(!null) // true
// !!: 将其他的数据类型转换为 boolean 类型 , 相当于Boolean()
//栗子
console.log(Boolean('xiaohong')) //true
console.log(!!'xiaohong') // true 代码少一些 逼格高很多
● 如果是两个值比较是否相等,遵循这个规则:如果是 == 比较的话,会进行默认的数据类型转换
1、对象 == 对象 永远不相等
2、对象 == 字符串 先将对象转换为字符串(调用toString的方法),然后再进行比较
[]转换为字符串 ""
{}转换为字符串"[object Object]"
3、 对象 == 布尔值 对象先转换字符串(toString),然后再转化为数字(Number ''是0),布尔类型也转换为数字(true是1 false是0),最后让两个数字比较
4、 对象 == 数字 对象先转换字符串(toString),然后再转化为数字(Number ''是0)
5、 数字 == 布尔 布尔转换为数字
6、 数字 == 字符串 字符串转换为数字
7、 字符串 == 布尔 都转换为数字
8、 null == undefined 结果是true
9、 null 或者 undefined 和其他任何的数据类型比较都不相等
● 除了 == 是比较 , ===也是比较(绝对比较)
=== 是不会帮你自动转换类型的 如果数据类型不一样,绝对不相等
Object
let obj = { //通过字面量方式创建一个对象
name:'小红',
age:22
}
//增加属性
obj.height = '160cm'
//或者
obj['width'] = '45kg'
//修改属性
obj.width = '43kg'
//查询属性
console.log(obj.age)
//删除属性
obj.age = null //假删除
delete obj.age //真删除
console.log(obj)
对象数据类型中, 还可以具体的细分:
对象类(Object) 、 数组类(Array)、正则类(RegExp)、时间类(Date)、字符串类(String)、布尔类(Boolean)、Math数学函数....
let obj = {}
let arr = []
let reg = /^$/
js中对象、类、实例的区别: 对象是泛指, js中万物皆对象,类是对 对象的具体的细分, 实例是类中的一个具体的事物
栗子: 自然界中万物皆对象,所有的东西都可以分为:人类、植物类、动物类、物体类
每一个人都是人类中的一个具体的实例
基本数据类型和引用数据类型的区别
let num1 = 12
let num2 = num1 // 把num1变量代表的值给了num2变量
num2++
console.log(num1,num2)
let obj1 = {
name:'xiaoyan'
}
let obj2 = obj1 // 这样相当于把 obj1的引用地址给了 obj2 , 相当于把房间钥匙给了obj2
obj2.name = 'xiaohong' // obj2拿到了obj1的引用地址 相当于拿到房间钥匙 所以obj2所做的修改都是会影响到obj1的,因为是同一个房间
console.log('obj1',obj1) //name:'xiaohong'
console.log('obj2',obj2) //name:'xiaohong'
// 基本数据类型没有跟着改变, 引用数据类型跟着改变了
基本数据类型和引用数据类型的本质区别:
基本数据类型操作的是值,而引用数据类型操作的是对新空间的引用地址
基本数据类型 :
基本数据类型是把值直接的给变量, 接下来在操作的过程中,直接拿这个值操作的,可能两个变量存储一样的值,但两个是互不影响的,其中一个改变,另一个也不会有任何的影响
引用数据类型:
1、定义一个变量
2、开辟一个新的空间,然后把属性名和属性值保存在这个空间中,并且有一个空间地址
3、把空间的地址给了这个变量,变量并没有存储这个数值,而存储的是对这个空间引用的地址
4、接下来我们把这个地址告诉给了另外一个变量,另外一个变量存储的也是这个地址,此时两个变量操作的是同一个空间
5、其中一个改变了空间的内容,另一个也会跟着改变
判断语法
switch case 要注意的点
1、每一种case 情况下都要加break(有 return 也可以);如果不加break,不管后面的代码是否成立,都会执行,这就是跳楼现象
2、每一种 case情况相当于 === 的比较, 所以用的时候一定要注意数据类型是否一致
循环注意点
break/continue
● break:在循环体中,出现break,整个循环就直接的结束了
● continue:在循环体中,出现continue,当前这一轮的循环就结束了,继续下一轮的循环
for in 循环
// for in 循环 : 用来循环一个对象中的数学名和属性值的
let obj = {
name : '小红',
age : 22,
height:'160cm',
hobby:'吃吃吃',
}
// 顺序问题: 首先循环数字的属性名(按照从小到大),再把剩下的属性名按照我们写的顺序循环
for(let key in obj){
console.log(`${key} ${obj[key]}`) //key:属性名 obj[key]:属性值
}
// 在 for in 中, 只能通过对象名[key] 来获取 不能写 obj.key
// 顺序问题: 首先循环数字的属性名(按照从小到大),再把剩下的属性名按照我们写的顺序循环
let obj2 = {
name : '小燕',
age : 22,
height:'160cm',
hobby:'吃吃吃',
2:10086,
1:10010,
}
for(let key in obj2){
console.log(`${key} ${obj2[key]}`) //key:属性名 obj[key]:属性值
}
//控制台输出
// 1 10010
// 2 10086
// name 小燕
// age 22
// height 160cm
// hobby 吃吃吃
function(函数)
● 函数 -> 具备某个功能的一个方法,方法本身是没有什么意义的,只有执行这个方法实现了对应的功能才有自己的价值
● 函数由两部分组成:创建一个函数、执行这个函数
// function 方法名(){
// //函数体: 存放的是某个功能实现的JS代码
// }
// 方法名()
1、创建一个函数(原理)(重点)
1、首先开辟一个新的内存空间,浏览器为其分配一个16进制的地址,我们假设地址为:xxxfff00
2、把函数体中的JS代码当做"字符串"存储到内存空间中
3、再把这个地址赋值给当前的函数名
function sum (){
var a = 1;
var b = 2;
console.log(a + b)
}
sum // -> sum 后面不加小括号,代表的就是当前函数本身
sum() // -> sum 后面加小括号,代表的执行当前函数
// 函数执行的目的:把函数之前存储的哪些字符串变为JS代码,然后在让JS代码从上到下依次的执行
2、函数的执行
1、当函数执行的时候,首先会提供一个供函数体中代码执行的环境 => "私有作用域"
2、把函数体中的代码字符串变为代码从上到下执行
3、概念
● 函数执行的时候,首先会形成一个新的私有作用域,供函数体中的代码从上到下执行
● 形成的哪个私有的作用域,把我们函数体中的代码都包起来了,保护了里面的私有的变量不受外界的干扰(外面获取不到也修改不了)
● 我们把函数执行的时候形成的这种机制叫做"闭包",按照这些理解,每一个函数都是一个闭包
形参
function sum(num1,num2){ // -> num1/num2就是我们设定的形参"变量",他就是当前函数的两个入口 这两个相当于进行了 var num1;var num2;的操作
var total = null
total = num1 + num2
console.log(total)
}
sum(1,2) // num1 =1 num2 = 2
sum(1) // num1 = 1 num2 = undefined 定义了形参执行的时候没有传递值,默认形参的值就是undefined 因为只定义没赋值的都是undefined
arguments
● arguments:函数天生自带的(不管写没写形参,也不管是否传递值,arguments始终都是存在的),用来接收函数传递进来的参数值的一个集合
● console.log(typeof arguments) // "object" 他是一个对象数据类型的值
● ->观察的它结构发现,它是以数字作为索引,索引从零开始逐渐递增,索引0存储的是第一个参数,索引1存储的是第二个参数,以此类推... ; 有一个叫做length的属性代表一共传递了多少个参数; 它不是一个数字,我们把它称之为类数组;
● callee:function sum()... 它还有一个自己特殊的属性callee,代表当前函数本身
function sum(){
let result = 0
for(let i = 0 ; i < arguments.length; i++){
result += arguments[i]
}
return result
}
const result = sum(100,222,3333,4444,565)
console.log(result)
return
function sum(num1,num2){
var total = null
total = num1 + num2
}
sum(100,200)
console.log(total) //Uncaught ReferenceError: total is not defined
● total这个变量没有定义 ==> 函数执行的时候,首先会形成一个私有的作用域,包含里面的内容不受外界的干扰(闭包),导致了在函数体中定义的变量total,在函数体的外面不能直接的获取到
function sum1(num1,num2){
var total = null
total = num1 + num2
return total // return 就是当前函数提供给我们的出口,因为如提供出口的话,闭包的机制导致了在函数体的外面无法获取里面total的值,如果想在外面用total的值,只需要通过 return 把 total 的值返回给外面即可 ==> "返回值机制"
// 外面想用的值,我们就把那个值返回 -> return total; 并不是把变量返回给外面,而是把变量存储的值返回给外面
// 如果这个函数没有 return ,那么默认的返回值就是undefined
}
var total = sum1(100,200) //首先把函数sum1执行,然后把sum执行的返回值赋值给外面的变量total
function fn(){
console.log('1')
return
console.log('2') //2不会输出 ,因为 return 还有终止函数中代码执行的作用
}
fn()
Array
let arr = [12,34,54,64]
console.dir(arr)
//控制台输出
// 0: 12
// 1: 34
// 2: 54
// 3: 64
// length: 4
// __proto__: Array(0)
for(let i = 0; i < arr.length;i++){
console.log(arr[i])
//输出
// 12
// 34
// 54
// 64
}
// 数组中有一个叫做length的属性,这个属性是浏览器天生就给数组增加的(不是我们自己编写的属性),这个属性属于当前数组"不可枚举的属性"
for(let key in arr){
// for in 循环是用来遍历一个对象中属性名和属性值的,但是对于当前对象不可枚举的属性我们通过它是遍历不到的;例如:我们无法便利道arr.length这个属性 (for in 循环是遍历原型链上面可枚举的属性) 来自于你所不知道的javaScript书籍
console.log(arr[key])
//输出
// 12
// 34
// 54
// 64
}
数组的常用方法
● Array.push
let arr = [1,2,3,4,5]
//1、push:向数组的末尾增加新的内容
// => 参数: 向末尾增加哪些内容就传递谁,而且可以传递多个值,统一向末尾增加多项
// => 返回值: 新增加后数组的长度
// => 原来的数组已经发生了改变
let res = arr.push(6)
console.log(arr) //原数组 [1, 2, 3, 4, 5, 6]
console.log(res) //返回值 6 返回值是数组的长度
// => 扩展:不想使用push,也想向数组的末尾增加内容
arr[arr.length] = 10
console.log(arr)
● Array.pop
//2、pop:向数组的末尾删除内容
// => 参数: 没有
// => 返回值: 被删除的那一项内容
// => 原来的数组会发生改变
let res = arr.pop()
console.log(arr) //[1, 2, 3, 4]
console.log(res) //5
// => 扩展:不用pop想删除最后一项的内容
arr.length--
console.log(arr)
● Array.shift
//3、shift:删除数组中的第一项
// => 参数: 没有
// => 返回值: 被删除的那一项内容
// => 原来的数组会发生改变
let res = arr.shift()
console.log(arr) //[1, 2, 3, 4]
console.log(res) //1
● Array.unshift
//4、unshift:向数组开头增加一项
// => 参数: 向开头增加哪些内容就传递谁,而且可以传递多个值,统一向末尾增加多项
// => 返回值: 新增加后数组的长度
// => 原来的数组会发生改变
let res = arr.unshift(100,200)
console.log(arr) //[100, 200, 1, 2, 3, 4, 5]
console.log(res) //7
● Array.splice
//4、splice:它既能实现上传,也能实现增加,还能实现修改
// => 参数: 两个参数
// => 返回值: 一个新的数组
// => 原来的数组会发生改变
//[删除]
let arr = [1,2,3,4,5,6,7,8,9]
// arr.splice(n,m) 从索引n开始,删除m各元素,把删除的内容以一个新的数组的方式返回,原来的数组改变
let res = arr.splice(2,3)
console.log(res) // [3, 4, 5]
console.log(arr) // [1, 2, 6, 7, 8, 9]
// arr.splice(n) 从索引n开始,删除到数组的末尾
// arr.splice(0) 把原来的数组每一项都删除掉(清空数组每一项),把之前的每一项的值以一个新数组返回(把之前的数组克隆了一份一模一样的,这样的克隆会修改原来的数组)
// arr.splice() 什么不都传的话,数组中一项都没删除,返回的是一个空数组
//[修改]
// => 参数: 三个参数
// => 返回值: 删除的内容已一个新的数组返回
// => 原来的数组会发生改变
// splice(n,m,x) 从索引n开始,删除m个,用x替换删除的部分
let arr = [1,2,3,4,5,6,7,8,9]
let res = arr.splice(2,4,1000,1001)
console.log(arr) //[1, 2, 1000, 1001, 7, 8, 9]
console.log(res) //[3, 4, 5, 6]
//[增加]
// => 参数: 三个参数
// => 返回值: 空数组
// => 原来的数组会发生改变
// splice(n,0,x) 从索引n开始,一个都不删除(返回的结构是一个空数组),把x增加到索引n的前面,原来的素组改变
let arr = [1,2,3,4,5,6,7,8,9]
let res = arr.splice(2,0,1000,1001)
console.log(arr) //[1, 2, 1000, 1001, 3, 4, 5, 6, 7, 8, 9]
console.log(res) //[]
● Array.slice
//slice :实现数组的截取,在原来的数组中截取某一部分
// => 参数: 两个参数
// => 返回值: 找到的部分以一个新数组返回
// => 原来的数组不会发生改变
// slice(n,m) 从索引n开始,找到索引为m处(但是不包含m),将找到的部分以一个新的数组返回,原来的数组不变
// slice(n) 从索引n开始一直找到数组的末尾
// slice(0)|| slice() 把原来的数组克隆一份一模一样的新数组返回
let arr = [1,2,3,4,5,6,7,8,9]
let newArr = arr.slice(3,6)
console.log(newArr) //[4, 5, 6]
console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
● Array.concat
//concat:把两个数组拼接到一起,原来的数组不变
// => 参数: 两个参数
// => 返回值: 返回一个新的数组
// => 原来的数组不会发生改变
// arr1.concat(arr2) 把 arr1和 arr2进行拼接,arr2在后面
// arr1.concat() 把arr1 克隆一份一模一样的数组
let arr1 = [1,2,3,4,5,6,7,8,9]
let arr2 = [10,11,12,13,14]
let newArr = arr1.concat(arr2)
console.log(newArr) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
console.log(arr1) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
● Array.toString
// 把数组换为字符串
// toString:把数组转换为字符串,原来的数组不变
// => 参数: 没有参数
// => 返回值: 返回一个新的字符串
// => 原来的数组不会发生改变
let arr = [1,2,3,4,5]
let res = arr.toString()
console.log(res) //1,2,3,4,5
● Array.join
// 把数组换为字符串
// join:按照每一个分隔符,把数组中的每一项拼接成一个字符串,原来的数组不变
// => 参数: 一个参数
// => 返回值: 返回一个新的字符串
// => 原来的数组不会发生改变
let arr = [1,2,3,4,5]
let res = arr.join('★')
console.log(arr) //[1, 2, 3, 4, 5]
console.log(res) //1★2★3★4★5
// =>扩展:eval -> JS中把字符串变为JS表达式执行的一个方法
console.log(eval("1+2+3+4+5")) //15
//题目: 把数组中的每一项进行相加求和
let arr = [1,2,3,4,5];
console.log(eval(arr.join('+'))) // 15
● Array.reverse
// 数组的排序和排列
// reverse:把数组倒过来排列
// => 参数: 没有参数
// => 返回值: 新数组
// => 原来的数组会发生改变
let arr = [1,2,3,4,5]
arr.reverse()
console.log(arr) //[5, 4, 3, 2, 1]
● Array.sort
// 数组的排序和排列
// sort:给数组进行排序
// => 参数: 函数
// => 返回值: 一个新数组
// => 原来的数组会发生改变
let arr = [110,2,214,532,234,6346,3345,37347,345345]
let newArr = arr.sort(function (a,b) {
return a - b //a - b 是 从小到大排序 b - a 是从大到小排序
})
console.log(arr) // [2, 110, 214, 234, 532, 3345, 6346, 37347, 345345]
● Array.indexOf/lastIndexOf
// indexOf/lastIndexOf
// => 参数: 要查找的参数
// => 返回值: 没找到是-1,找到就是索引
// => 原来的数组不会发生改变
// indexOf/lastIndexOf :当前内容在数组中第一次出现/最后一次出现位置的索引,如果数组中没有这一项,返回的结果是-1,如果有这一项,索引是几就返回几 , 原来的数组不变
//这样就可以验证当前的内容在数组中是否存在
let arr = [13,342,25235,36346,45747]
if(arr.indexOf('xiaohong') > -1){
//说明'xiaohong'存在数组中
}else{
//说明'xiaohong'不存在数组中
}
● Array.forEach/map
//forEach / map 都是用来遍历数组中的每一项的
// => 参数: 函数
// => 返回值:没有返回值/map返回一个新数组
// => 原来的数组不会发生改变
// 函数值的第一个形参是遍历这一项的值,第二项是索引
let arr = [12,23,2523,346346,37346,34,346,36];
arr.forEach((item,index)=>{
console.log(item,index)
})
let o = arr.map((item,index)=>{
return item * 2
})
console.log(o) //[24, 46, 5046, 692692, 74692, 68, 692, 72]
Math
// Math 是属性函数,里面提供了几个操作数字的方法
// 1、Math.abs() 取绝对值
// 2、Math.ceil() 向上取整
// 3、Math.floor() 向下取整
// 4、Math.round() 四舍五入
// 5、Math.max(val1,val2,val3....) 最大值
// 6、Math.min(val1,val2,val3....) 最小值
// 7、Math.random() 获取[0-1) 之间的随机小数
// 获取[n-m] 之间的随机整数
// 公式: Math.round(Math.random() * (m-n) + n)
// 例如: 1-10 14-58
console.log(getRandom(58,14))
//获取随机数函数
function getRandom(n,m){
n = Number(n) // 不管传递的是什么,强制转换一下,只有两种情况: 数字和NaN
m = Number(m)
if(isNaN(n) || isNaN(m)){ //如果两个里面有一个不是有效数字,就返回[0-1)之间随机小数
return Math.random()
}
//如果 n 比 m 大了,我们默认交换位置
if(n > m){
[n,m] = [m,n] // ES6 的方法交换位置
}
// if(n > m){ 传统的交换方法
// let temp = n
// n = m
// m = temp
// }
return Math.round(Math.random() * (m - n) + n)
}
//小练习:获取四位不重复的 0 - 61 随机数
function getRandom4(){
let arr = []
for(let i = 0; i < 4; i++){
let temp = Math.round(Math.random() * (61 - 0) + 0)
if(arr.indexOf(temp) !== -1){
i-- //重复就 i-- 回退一次
continue // 直接下一次循环
}
arr.push(temp)
}
return arr
}
console.log(getRandom4())
String
1、字符串的查找
● charAt
● charCodeAt
// 一个字符串是由多个字符组成的
// str.length 获取字符串中字符的个数(字符串的长度)
// 字符串中也存在索引,也是从0开始
// 空格、换行这些特殊的符号也是一个字符
// 1、charAt(索引) 获取指定索引位置的字符
// charCodeAt(索引) 获取指定索引位置的字符对应的ASCII值
let str = 'good good study , day day up!'
console.log(str.charAt(3)) //d
console.log(str.charCodeAt(3)) //100
2、字符串的截取
● substr
● substring
● slice
// 2、字符串截取
// substr(n,m) 从索引n开始截取m个字符
// substring(n,m) 从索引n开始,找到索引m处(不包含m),将找到的字符返回
console.log(str.substr(0,15)) //good good study
console.log(str.substring(0,15)) //good good study
// slice(n,m) 从索引n开始,找到索引m处(不包含m),将找到的字符返回 slice支持负数作为索引,str.length + 负数索引
console.log(str.slice(-11,-1)) //day day up
//如果只写了一个n,没有m:代表截取到末尾位置
3、查找字符串
● indexOf
● lastIndexOf
// indexOf(字符串):获取指定字符串在字符串中第一次出现的索引位置
// lastIndexOf(字符串): 获取指定字符串在字符串中最后一次出现的索引位置
// 如果没有这个字符, 返回的是 -1 ,基于这个理念我们经常用这两个方法判断字符串中是否包含某个字符
console.log(str.indexOf('!')) // 15
console.log(str.lastIndexOf('!')) // 29
console.log(str.indexOf('xiao')) // -1
4、大小写转换
● toLowerCase
● toUpperCase
// toLowerCase:将所有字母转为小写
// toUpperCase:将所有字母转为大写
console.log(str.toLowerCase())
console.log(str.toUpperCase())
5、替换
● replace
// replace(要替换的老字符,替换成的新字符)
// 在不使用正则的情况下,每一次调用方法只能调用一次
// 一般情况下,都是用正则处理的
// console.log(str.replace('good','xiaohong')) 'xiaohong good study! , day day up!'
console.log(str.replace(/good/g,"xiaohong"))
6、分割
● split
let s = '1+2+3+4'
// console.log(s.split('+')) //["1", "2", "3", "4"]
console.log(s.split('')) //["1", "+", "2", "+", "3", "+", "4"]
// 7、match 正则常用的
字符串和Math综合小练习
// 小练习 四位验证码
let str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
console.log(getCode(str))
function getCode(str){ //获取4个字验证码
let code = '' //初始化验证码字符串
for(let i = 0; i < 4; i++){ //四个验证码,遍历四次
code += str.charAt(getRandom(0,61)) // 0-61的下标取出str的 索引添加到code去
}
return code //返回验证码字符串
}
//获取随机数函数
function getRandom(n,m){
n = Number(n)
m = Number(m)
if(isNaN(n) || isNaN(m)){
return Math.random()
}
if(n > m){
[n,m] = [m,n]
}
return Math.round(Math.random() * (m - n) + n)
}
Date
// date
//获取当前自己电脑的时间
let time = new Date()
console.log(time) //Thu Sep 26 2019 20:09:27 GMT+0800 (中国标准时间) 时间格式数据(对象数据类型的)
function formatTime(){
let time = new Date()
let year = time.getFullYear() //获取年份
let month = time.getMonth() + 1 //获取月份 0-11 +1 之后显示1-12月
let day = time.getDate() // 获取天
let w = time.getDay() // 0-6 代表周日-周六
let wStr = '日一二三四五六'
let week = wStr.charAt(w)
let hours = time.getHours() // 小时
let minutes = time.getMinutes() // 分
let seconds = time.getSeconds() // 秒
let mlSeconds = time.getMilliseconds() //毫秒
return `${year}年 ${zero(month)}月 ${zero(day)}日 星期${week} ${zero(hours)}时 ${zero(minutes)}分 ${zero(seconds)}秒`
}
console.log(formatTime())
//补0
function zero(value){
return value < 10 ? '0' + value : value 
}
定时器
//定时器:设置一个定时器,再设置一个等待的时间,到达指定时间后,执行对应的操作
// window.setInterval([function],[interval])
//设置一个定时器,到达指定的时间[interval],执行操作[function],然后定时器并没有停止,以后每隔这么长时间都重新执行一次[function]
// window.setTimeout([function],[interval])
//设置一个定时器,到达指定的时间[interval],执行操作[function],定时器停止
//定时器的返回值是一个数字,代表的是第几个定时器,相当于我们去银行办理业务拿到的那个排队号
let count = 0
let timer1 = setTimeout(function(){
count++
console.log(count)
},1000)
let timer2 = setTimeout(function(){
count++
console.log(count)
},1000)
console.log(timer1) //1 标识在定时器队列里面排第 1 号
console.log(timer2) //2