JavaScript的原始类型并非对象类型,所以从理论上来说,它们是没有办法获取属性或者调用方法的,但是在开发中会经常这样操作,直接调用
<script>
var name = "Hello World"
var height = 1.8888888
// 在调用原始类型的属性或者方法时, 内部的操作 name = new String(name)
console.log(name.length)
console.log(name.split(" ")) //split函数,把一个字符串分割成字符串数组:,把空格改成逗号
console.log(height.toFixed(2)) //toFixed函数,把数字转换为字符串,结果的小数点后有指定位数的数字:
// 原始类型默认也是可以手动的创建对象(没有必要这样来做)
var name1 = new String("Hello World")
console.log(typeof name1) //object
</script>
原始类型可以直接调用函数的原因:
原始类型是简单的值,默认并不能调用属性和方法;
但JavaScript为了可以使其可以获取属性和调用方法,对其封装了对应的包装类型
包装类型的使用过程:
根据原始值,创建一个原始类型对应的包装类型对象;
调用对应的属性或者方法,返回一个新的值;
创建的包装类对象被销毁;
通常JavaScript引擎会进行很多的优化,会跳过创建包装类的过程在内部直接完成属性的获取或者方法的调用。
Number类型,有一个对应的数字包装类型。
Number属性补充:
Number.MAX_VALUE
JavaScript 中最大数值(1.7976931348623157e+308)
Number.MIN_VALUE
JavaScript 中最小数值(5e-324)
Number.MAX_SAFE_INTEGER
JavaScript 中最大的安全整数 (2^53 - 1);
Number.MIN_SAFE_INTEGER
JavaScript 中最小的安全整数 -(2^53 - 1)
Number实例方法补充:
方法一:toString(base)
,将数字转成字符串,并且按照base进制进行转化
base 的范围可以从 2 到 36,默认情况下是 10
注意:如果是直接对一个数字操作,需要使用...
运算符;
var num = 1000
console.log(num.toString(8)) //把10000转换成八进制
console.log(325..toString(2)) //直接把325转换成二进制 101000101
方法二:toFixed(digits)
,格式化一个数字,保留digits位的小数;
var pi = 3.1415926
console.log(pi.toFixed(3)) //保留三位小数,得到 3.142
Number类方法补充:
方法一:Number.parseInt(string[, radix])
,将字符串解析成整数,也有对应的全局方法parseInt;
方法二:Number. parseFloat(string)
,将字符串解析成浮点数,也有对应的全局方法parseFloat;
var num1 = "123.521"
console.log(Number(num1).toFixed(0)) //124
console.log(Number.parseInt(num1)) //123
console.log(Number.parseFloat(num1)) // 123.521
Math是一个内置对象(不是一个构造函数),它拥有一些数学常数属性和数学函数方法;
Math常见的方法:
Math.PI
:圆周率,约等于 3.14159;
Math.floor
:向下舍入取整
Math.ceil
:向上舍入取整
Math.round
:四舍五入取整
Math.random
:生成0~1的随机数(包含0,不包含1)
Math.pow(x, y)
:返回x的y次幂
// random: 随机生成 [0, 1)
// 需求: [5~50)的随机数
// [a, b)
// y = a
// x = b - a
// Math.floor(Math.random() * x) + y
for (var i = 0; i < 1000; i++) {
var randomNum = Math.floor(Math.random() * 45) + 5
console.log(randomNum)
}
String常见的属性: String.length
获取字符串的长度
访问字符串的字符:
使用方法一:通过字符串的索引 str[0] ,没有找到值会返回undefined;
使用方法二:通过str.charAt(pos)
方法 ,没有找到会返回空字符串;
字符串的遍历:
方式一:普通for循环
方式二:for..of
遍历
<script>
var message = "Hello World"
// 1.属性: length
console.log(message.length) //11
// 2.访问字符串中某个位置的字符
// console.log(message[4]) //打印字母o
// console.log(message.charAt(4)) //打印字母o
// console.log(message[20]) //没有找到值会返回undefined;
// console.log(message.charAt(20)) //没有找到会返回空字符串;
// 3.字符串的遍历
// for普通遍历
for (var i = 0; i < message.length; i++) {
console.log(message[i])
}
// for..of的遍历 -> 迭代器
// 目前可迭代对象: 字符串/数组
// 对象是不支持for..of
// String对象内部是将字符串变成了一个可迭代对象
for (var char of message) {
console.log(char)
}
</script>
字符串的不可变性: 字符串在定义后是不可以修改的,所以下面的操作是没有任何意义的;
var message = "Hello World"
message[2] = "a"
console.log(message) //打印出来仍是 Hello World
改变字符串的操作中,大多是生成了一个新的字符串,比如改变字符串大小的两个方法:
toLowerCase()
:将所有的字符转成小写;
toUpperCase()
:将所有的字符转成大写
var message = "Hello World"
var message1 = message.toUpperCase()
console.log(message1) //HELLO WORLD
var message2 = message.toLowerCase()
console.log(message2) //hello world
String提供了如下方法:
方法一:查找字符串的索引位置 str.indexOf ( searchValue [ , fromIndex ] )
在字符串str里面是否查找到searchValue
从fromIndex开始,查找searchValue的索引位置,找到则返回索引数字;(索引位置0,1,2,3,…)
如果没有找到,那么返回-1;
有一个相似的方法,叫lastIndexOf
,从最后开始查找(用的较少)
方法二:是否包含字符串 str.includes ( searchString [ , position ] )
判断,在字符串str里面是否包含searchString
从position位置开始查找searchString, 根据情况返回 true 或 false。这是ES6新增的方法;
方法三:以xxx开头 str.startsWith ( searchString [ , position ] )
从position位置开始,判断字符串是否以searchString开头;
这是ES6新增的方法,下面的方法也一样;
方法四:以xxx结尾.。 str.endsWith ( searchString [ , length ] )
在length长度内,判断字符串是否以searchString结尾;
方法五:替换字符串 str.replace ( regexp | substr , newSubStr | function] )
查找到对应的字符串,并且使用新的字符串进行替代;(括号内左边是等待被替换的字符串 ,括号内右边是新字符串)
这里也可以传入一个正则表达式来查找,也可以传入一个函数来替换;
<script>
var message = "my name is xixi"
var name = "xixi"
// 判断一个字符串中是否有另外一个字符串
// 1.indexOf(searchString, fromIndex)
/*
index:
情况一: 搜索到, 搜索字符串所在索引位置(数字0,1,2,3,..)
情况二: 没有搜索到, 返回-1
*/
var index = message.indexOf(name)
if (message.indexOf(name) !== -1) {
console.log("message中包含name")
} else {
console.log("message不包含name")
}
// 2.includes: ES6中新增一个方法, 就是用来判断包含关系,true false
if (message.includes(name)) {
console.log("message中包含name")
}
// 3.startsWith: 判断是否以xxx开头 true false
if (message.startsWith("my")) {
console.log("message以my开头")
}
// 4.endsWith: 判断是否以xxx结束 true false
if (message.endsWith("xixi")) {
console.log("message以xixi结尾")
}
// 5.replace 替换字符串 hah 替换 xixi
var newMessage = message.replace("xixi", "hah")
console.log(message) //my name is xixi
console.log(newMessage) // my name is hah
//函数替换 xixi
var newName = "hah"
var newMessage = message.replace("xixi", function() {
return newName.toUpperCase() //返回大写的HAH
})
console.log(newMessage) // my name is HAH
</script>
<script>
var message = "Hello World"
// 获取子字符串
console.log(message.slice(3, 7)) //lo W
console.log(message.slice(3, -1)) //lo Worl
console.log(message.slice(3)) //lo World 没有指明末尾位置, 一直持续到末尾
// substr
console.log(message.substr(3, 7)) //lo Worl
</script>
方法六:拼接字符串 str.concat(str2 , [, ...strN])
方法七:删除首尾空格 str.trim()
方法九:字符串分割 str.split ( [ separtator [ , limit ] ] )
separator:以什么字符串进行分割,也可以是一个正则表达式;
limit:限制返回片段的数量;
<script>
var str1 = "Hello"
var str2 = "World"
var str3 = "haha"
// 1.字符串拼接
// +
// var newString = str1 + str2 + str3
// console.log(newString)
// concat方法: 链式调用
var newString2 = str1.concat(str2).concat(str3)
var newString3 = str1.concat(str2, str3, "abc", "cba")
console.log(newString2) //HelloWorldhaha
console.log(newString3) //HelloWorldhahaabccba
// 2.删除首尾的空格
console.log(" why abc ".trim()) //why abc
// 3.字符串切割split
var message = "abc-cba-nba-mba"
var items = message.split("-")
console.log(items) //打印的是数组 ['abc', 'cba', 'nba', 'mba']
var newMessage = items.join("*")
console.log(newMessage) //打印出来的是 abc*cba*nba*mba
</script>
数组(Array)是什么
对象允许存储键值集合,但是在某些情况下使用键值对来访问并不方便; 比如说一系列的商品、用户、英雄,包括HTML元素, 存储时需要一种有序的集合,里面的元素是按照某一个顺序来排列的; 这个有序的集合,可以通过索引来获取到; 这个结构就是数组(Array);
数组和对象都是一种保存多个数据的数据结构,可以通过[]
来创建一个数组,数组是一种特殊的对象类型;
创建一个数组有两种语法
[ "abc" , "cba" , "acb" ]
new Array ( "abc" , "cba" , "acb")
var arr1 = [ "abc" , "cba" , "acb" ]
var arr2 = new Array ( "abc" , "cba" , "acb")
创建一个数组时,设置数组的长度(很少用) new Array ( 数字)
var arr3 = new Array ( 3 ) //数组长度为3
var arr4 = [ 3 ] //数组中的内容 是 3
数组元素从0开始编号(索引 index )。
一些编程语言允许我们使用负数索引来实现这一点,例如 fruits[-1]
JavaScript并不支持这种写法;
var arr1 = [ "abc" , "cba" , "acb" ]
console.log( arr1 [ 0 ] ) // 第一个元素
console.log( arr1 [ arr1.length-1 ]) // 最后一个元素
访问数组中的元素:
通过中括号[]
访问 ,只能是大于等于0的索引数字;
arr.at ( i )
: 如果 i >= 0,则与 arr[i] 完全相同; 对于 i 为负数的情况,它则从数组的尾部向前数。
var arr1 = [ "abc" , "cba" , "acb" ]
console.log( arr1 [ 0 ] ) // 第一个元素
console.log( arr1 [ -1 ] ) // 显示/undefined,不支持这么访问
console.log( arr1.at (-1) ) // 访问最后一个元素,支持这么访问
修改数组中的元素
var arr1 = [ "abc" , "cba" , "acb" ]
arr1[1] = "aaa"
console.log( arr1 [1] ) // aaa
删除和添加元素虽然也可以通过索引来直接操作,但是开发中很少这样操作。
var arr1 = [ "abc" , "cba" , "acb" ]
arr1[ 3 ] = "ccc"
arr1[ 8 ] = "bbb"
console.log( arr1 ) // 长度为9
delete names[1] //删除索引位置为[1]的元素内容,删除后,该元素为undefined
在数组的尾端添加或删除元素:【快】
push
在末端添加元素.
pop
从末端取出一个元素.
var arr = [ "abc" , "cba" , "acb" ]
arr.push ( "aaa" , "bbb" , "ccc" )
console.log( arr ) //"abc" , "cba" , "acb" , "aaa" , "bbb" , "ccc"
arr.pop()
arr.pop()
console.log( arr ) //"abc" , "cba" , "acb" , "aaa"
在数组的首端添加或删除元素:【慢】
shift
取出队列首端的一个元素,整个数组元素向前前移动;
unshift
在首端添加元素,整个其他数组元素向后移动;
var arr = [ "abc" , "cba" , "acb" ]
arr.unshift ( "aaa" , "bbb" )
console.log( arr ) // "aaa" , "bbb" , "abc" , "cba" , "acb"
arr.shift ( )
console.log( arr ) // "bbb" , "abc" , "cba" , "acb"
push/pop 方法运行的比较快,而 shift/unshift 比较慢。
在数组中间某个位置添加、删除、替换元素:【强大】
arr.splice ( start [ , deleteCount [ , item1 [ , item2 [ , ... ] ] ] ] )
方法可以说是处理数组的利器
从start位置开始,处理数组中的元素;
deleteCount:要删除元素的个数,如果为0或者负数表示不删除;
item1, item2, …:在添加元素时,需要添加的元素;
var arr = [ "abc" , "cba" , "acb" , "aaa" , "bbb" ]
//删除以索引1开始 、总共删除2个的 元素 ,其余元素往前补充
arr.splice ( 1 ,2 ) // "abc" , "aaa" , "bbb"
//在索引 1 处新增 元素 ,该索引元素往后移 , 设置第二个数字为0
arr.splice ( 1 ,0 , "ccc" , "ddd" ) // "abc" , "ccc" , "ddd" , "acb" , "bbb"
//替换 先抛弃以索引1开始 、总共2个的 元素 , 再补充新元素
arr.splice ( 1 ,2 , "eee" , "hhh" , "xxx" ) // "abc" , "eee" , "hhh" , "xxx" , "acb" , "bbb"
length、属性用于获取数组的长度, 当修改数组的时候,length 属性会自动更新。
可以在原来的长度基础上,增加Length的长度,实现扩容;
但是如果直接减少Length的长度,数组就会被截断。
清空数组最简单的方法就是:arr.length = 0
普通for循环遍历
for..in
遍历,获取到索引值
for..of
遍历,获取到每一个元素(内容)
var names = ["abc", "cba", "nba", "mba"]
// 普通的for循环
for (var i = 0; i < names.length; i++) {
console.log(names[i])
}
// for..in
for (var index in names) {
console.log(index, names[index])
}
// for..of
for (var item of names) {
console.log(item)
}
数组中存放的是对象类型
arr.slice
:用于对数组进行截取(类似于字符串的slice方法)。 包含bigin元素,但是不包含end元素;
arr.concat
:创建一个新数组,其中包含来自于其他数组和其他项的值。
arr.join
:将一个数组的所有元素连接成一个字符串并返回这个字符串。
arr.indexOf
: 查找某个元素的索引
arr.includes
:判断数组是否包含某个元素
注意:find
和 findIndex
方法 ,是String类没有的,直接查找元素或者元素的索引(ES6之后新增的语法)
find是高阶函数,可以用函数作为输入值或返回值。
var students = [
{ id: 100, name: "why", age: 18 },
{ id: 101, name: "kobe", age: 30 },
{ id: 102, name: "james", age: 25 },
{ id: 103, name: "why", age: 22 }
]
//find函数遍历数组students,然后找到 Id == 101 的元素。item作为参数,自动接收students数组的元素
var stu = students.find ( function ( item ) {
if (item.id === 101) return true
})
console.log(stu)
自主实现find高阶函数
// 1.原始类型的查找
var names = ["abc", "cba", "nba", "mba"]
// 原生find方法
var findName = names.find(function(item, index, arr) {
console.log(item, index, arr)
return item === "nba"
})
console.log(findName)
// 2.数组中对象类型的查找
var students = [
{ id: 100, name: "why", age: 18 },
{ id: 101, name: "kobe", age: 30 },
{ id: 102, name: "james", age: 25 },
{ id: 103, name: "why", age: 22 }
]
// var findStu = students.find(function(item) {
// return item.id === 101
// })
// console.log(findStu)
// 3.自己实现Find(百分90以上的不要求)
Array.prototype.myFind = function(fn) {
// var item = undefined
for (var i = 0; i < this.length; i++) {
var isFlag = fn(this[i], i, this)
if (isFlag) {
// item = this[i]
// break
return this[i]
}
}
// return item
}
var findStu = students.myFind(function(item, index, arr) {
console.log(item)
return item.id === 101
})
console.log(findStu)
</script>
sort方法也是一个高阶函数,用于对数组进行排序,并且生成一个排序后的新数组
arr.sort ( [ compareFunction ] )
如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 前面;
如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变;
如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 前面;
谁小谁排在前面;
reverse()
方法将数组中元素的位置颠倒,并返回该数组
var nums = [20, 4, 10, 15, 100, 88]
// // sort: 排序
nums.sort(function(item1, item2) {
// item1和item2进行比较
// 返回是 整数
// 谁小谁在前
// return item1 - item2
return item2 - item1
})
console.log(nums)
console.log(nums.reverse())
// 复杂类型的排序
var students = [
{ id: 100, name: "why", age: 18 },
{ id: 101, name: "kobe", age: 30 },
{ id: 102, name: "james", age: 25 },
{ id: 103, name: "curry", age: 22 }
]
students.sort(function(item1, item2) {
return item1.age - item2.age
})
console.log(students)
arr.forEach
: 遍历数组,并且让数组中每一个元素都执行一次对应的方法;
// 1.forEach函数
var names = ["abc", "cba", "nba", "mba"]
// 三种方式, 新增一种方式 遍历数组中的每一个元素
names.forEach(function(item) {
console.log(item, this)
}, { name: "why" })
arr.map
map() 方法创建一个新数组;
这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成;
// map函数: 映射 例如求每个元素的平方值
var nums = [11, 20, 55, 100, 88, 32]
var newNums = nums.map(function(item) {
return item * item
})
console.log(newNums) // [121, 400, 3025, 10000, 7744, 1024]
arr.filter
filter() 方法创建一个新数组;
新数组中只包含每个元素调用函数返回为true的元素;
// filter函数: 过滤
var nums = [11, 20, 55, 100, 88, 32]
//for循环实现过滤
var newNums = []
for (var item of nums) {
if (item % 2 === 0) {
newNums.push(item)
}
}
// filter实现 过滤出为偶数的元素
var newNums = nums.filter(function(item) {
return item % 2 === 0
})
console.log(newNums)
arr.reduce
用于计算数组中所有元素的总和;
对数组中的每个元素按序执行一个由您提供的 reducer 函数;
每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值;
// 4.reduce
var nums = [11, 20, 55, 100, 88, 32]
//for 循环实现求和
var result = 0
for (var item of nums) {
result += item
}
console.log(result) //306
// 第一次执行: preValue->0 item->11
// 第二次执行: preValue->11 item->20
// 第三次执行: preValue->31 item->55
// 第四次执行: preValue->86 item->100
// 第五次执行: preValue->186 item->88
// 第六次执行: preValue->274 item->32
// 最后一次执行的时候 preValue + item, 它会作为reduce的返回值
// initialValue: 初始化值, 第一次执行的时候, 对应的preValue
// 如果initialValue没有传的话,默认为0
var result = nums.reduce(function(preValue, item) {
console.log(`preValue:${preValue} item:${item}`)
return preValue + item
}, 0)
console.log(result) 306
// reduce练习
var products = [
{ name: "鼠标", price: 88, count: 3 },
{ name: "键盘", price: 200, count: 2 },
{ name: "耳机", price: 9.9, count: 10 },
]
var totalPrice = products.reduce(function(preValue, item) {
return preValue + item.price * item.count
}, 0)
console.log(totalPrice) //763
// 综合练习: 【套娃版】
var nums = [11, 20, 55, 100, 88, 32]
// 过滤所有的偶数, 映射所有偶数的平方, 并且计算他们的和
var total = nums.filter(function(item) {
return item % 2 === 0
}).map(function(item) {
return item * item
}).reduce(function(preValue, item) {
return preValue + item
}, 0)
console.log(total) //19168
// 精简版
var total = nums.filter(item => item % 2 === 0)
.map(item => item * item)
.reduce((preValue, item) => preValue + item, 0)
console.log(total) //19168
< br>
在JavaScript中我们使用Date来表示和处理时间
new Date( );
new Date( value) ;
new Date ( datestring) ;
new Date( year,monthIndex [, day [, hours [, minutes [, seconds [,milliseconds]]]]]);
// 创建Date对象的方式
// 1.没有传入任何的参数, 获取到当前时间
var date1 = new Date()
console.log(date1) //Mon May 29 2023 16:42:19 GMT+0800 (中国标准时间)
// 2.传入参数: 时间字符串
var date2 = new Date("2022-08-08")
console.log(date2) //Mon Aug 08 2022 08:00:00 GMT+0800 (中国标准时间)
// 3.传入具体的年月日时分秒毫秒
var date3 = new Date(2033, 10, 10, 09, 08, 07, 333)
console.log(date3) //Thu Nov 10 2033 09:08:07 GMT+0800 (中国标准时间)
// 4.传入一个Unix时间戳
// 1s -> 1000ms
var date4 = new Date(10004343433)
console.log(date4) //Mon Apr 27 1970 02:59:03 GMT+0800 (中国标准时间)
日期的表示方式有两种:
var date = new Date()
console.log(date) //Mon May 29 2023 16:46:50 GMT+0800 (中国标准时间)
console.log(date.toDateString()) //Mon May 29 2023
console.log(date.toISOString()) //2023-05-29T08:46:50.075Z
getFullYear()
:获取年份(4 位数);
getMonth():获取月份,从 0 到 11;
getDay():获取一周中的第几天,从 0(星期日)到 6(星期六);
getDate():获取当月的具体日期,从 1 到 31(方法名字有点迷);
getHours():获取小时;
getMinutes():获取分钟;
getSeconds():获取秒钟;
getMilliseconds():获取毫秒;
var date = new Date()
console.log(date) // Wed Jun 01 2033 16:52:20 GMT+0800 (中国标准时间)
console.log(date.toISOString()) //2023-05-29T08:52:20.135Z
// 1.获取想要的时间信息
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds()
console.log(year, month, day, hour, minute, second) //2023 5 29 16 52 20
console.log(`${year}/${month}/${day} ${hour}:${minute}:${second}`) // 2023/5/29 16:52:20
var weekday = date.getDay() // 一周中的第几天 也就是星期几
console.log(weekday) // 1
setFullYear(year, [month], [date])
setMonth(month, [date])
setDate(date)
setHours(hour, [min], [sec], [ms])
setMinutes(min, [sec], [ms])
setSeconds(sec, [ms])
setMilliseconds(ms)
setTime(milliseconds)
// 给date设置时间(了解)
date.setFullYear(2033)
// 自动校验
date.setDate(32)
console.log(date) // Wed Jun 01 2033 16:52:20 GMT+0800 (中国标准时间)
Unix时间戳:它是一个整数值,表示自1970年1月1日00:00:00 UTC以来的毫秒数
在JavaScript中,有多种方法可以获取这个时间戳:
new Date().getTime()
new Date().valueOf()
+new Date()
Date.now()
获取到Unix时间戳之后,可以利用它来测试代码的性能
// Date对象, 转成时间戳
var date = new Date()
var date2 = new Date("2033-03-03")
// 方法一: 当前时间的时间戳
var timestamp1 = Date.now()
console.log(timestamp1) //1685350912090
// 方法二/三将一个date对象转成时间戳
var timestamp2 = date.getTime()
var timestamp3 = date2.valueOf()
console.log(timestamp2, timestamp3) //1685350924530 1993420800000
// 方法四: 了解
console.log(+date) //1685350952758
// 计算这个操作所花费的时间
var startTime = Date.now()
for (var i = 0; i < 100000; i++) {
console.log(i)
}
var endTime = Date.now()
console.log("执行100000次for循环的打印所消耗的时间:", endTime - startTime)
// 封装一个简单函数
function testPerformance(fn) {
var startTime = Date.now()
fn()
var endTime = Date.now()
}
Date.parse(str)
从一个字符串中读取日期,并且输出对应的Unix时间戳.
作用等同于 new Date(dateString).getTime() 操作;
需要符合 RFC2822 或 ISO 8601 日期格式的字符串; 比如YYYY-MM-DDTHH:mm:ss.sssZ
其他格式也许也支持,但结果不能保证一定正常;
如果输入的格式不能被解析,那么会返回NaN;
var timeString = "12/12/2033"
// 1.方式一:
var date = new Date(timeString)
var timestamp = date.getTime() //2017929600000
// 2.方式二:
timestamp = Date.parse(timeString)
console.log(timestamp) //2017929600000