let obj={
a:99,
name:'小明'
};
Object.freeze(obj)
obj.a = 100
console.log( obj); // /输出99,因为冻结之后对象的内容无法改变
// 获取对象key值
// 定义默认值的时候
let a = null; // 代表定义的是引用类型
let b = undefind; // 代表定义的是基本类型
let aa = 'abcdf'
// 一个参数的时候都代表截取掉位置为1的数
console.log(aa.slice(1)) // bcdf
console.log(aa.substring(1)) // bcdf
console.log(aa.substr(1)) // bcdf
console.log(aa.slice(1,3)) // bc 第一个参数代表从哪里开始,第二个参数代表截取哪一个位置的前面
console.log(aa.substring(1,3)) // bc 第一个参数代表从哪里开始,第二个参数代表截取哪一个位置的前面
console.log(aa.substr(1,3)) // bcd 第一个参数代表从哪里开始,第二个参数代表截取几个
console.log(aa.slice(-3)) // cdf 从后面开始算三个
console.log(aa.substring(-3)) // abcdf 负数默认为0
console.log(aa.substr(-3)) // cdf 这个也是从后面开始算三个
console.log(aa.slice(-3,-1)) // cd 从后面开始算三个,第二个参数是截取到哪个位置
console.log(aa.substring(-3)) // abcdf 负数默认为0,这里所有负数都默认为0
console.log(aa.substr(-3,2)) // cd 这个也是从后面开始算三个,第二个参数代表截取几个let aa = 'abcdefg'
console.log(aa.slice(1)) // b
console.log(aa.substring(1)) // b
console.log(aa.substr(1)) // b
console.log(aa.slice(1,3)) // bc 第一个参数代表从哪里开始,第二个参数代表截取哪一个序号前面的
console.log(aa.substring(1,3)) // bc 第一个参数代表从哪里开始,第二个参数代表截取哪一个序号前面的
console.log(aa.substr(1,3)) // bcd bc 第一个参数代表从哪里开始,第二个参数代表截取几个
// repeat 复制字符串指定次数,并将它们连接在一起返回。
console.log('*'.repeat(5)) // *****
let aa = 'abcd'
// 如果存在这个字符就会返回这个字符的序号,如果不存在就会返回-1
// 第二个参数代表从第几个开始查找
console.log(aa.indexOf('a',2)) // -1
let aa = 'abcd'
// 如果存在这个字符就会返回true,如果不存在就会返回false
// 第二个参数代表从第几个开始查找
console.log(aa.includes('a',2)) // false
// 检测该字符串的开头是不是这个字符
let aa = 'abcd'
console.log(aa.startWith('a')) // false
// 检测该字符的结尾是不是这个字符
console.log(aa.endsWith('d')) // true
// parseInt
let aa = '99sss'
console.log(parseInt(aa)); // 99
// 字符串转换成数组
console.log(aa.split('')); // ["9", "9", "s", "s", "s"]
// 数组转换成字符串
let bb = ['aa','bb']
console.log(bb.join('')); // aabb
// 使用toString()
console.log(bb.toString()); // aa,bb
let cc = new String('aaa')
console.log(typeof cc); // Object
let aa = 100.33;
// 检测是不是int类型
console.log(Number.isSafeInteger(aa)); // false
// 加载到小数点后几位
console.log(aa.toFixed(1)); // 100.3
// 正常使用math的最大函数
console.log(Math.max(1,2,3));
// 加入要检测的是数组呢,因为max函数只能是再函数传的参数里面作为对比
let aa= [1,2,3]
// 所以解决办法就是
console.log(Math.max.apply(null,aa));
// 向上取整
console.log(Math.ceil(5.01));
// 向下取整
console.log(Math.floor(5.01));
// 四舍五入
console.log(Math.round(5.6));
// 检测脚本时间
// 方法一
let start = Date.now()
for (let index = 0; index < 20000000; index++) {}
let end = Date.now()
console.log((end - start) / 1000); // 0.012
// 方法二
console.time('aa')
for (let index = 0; index < 20000000; index++) {}
console.timeEnd('aa') // aa: 10.924ms
// new Date()的传参问题
// 方法一,时间格式
let date = new Date('2020-7-1 12:12:12')
console.log(date * 1); // 可以得到时间戳
console.log(date.getMonth()); // 6 因为月是从0开始算的
// 方法二,一个参数一个参数的格式
let data = new Date(2020,2,22,13,22,10)
console.log(data); // // 2020-03-22T05:22:10.000Z
// 方法三,数组的形式
let aa = [2020,2,22,13,22,10]
let data = new Date(...aa)
console.log(data); // 2020-03-22T05:22:10.000Z
// 时间戳与正常时间格式iso的转换
let data = new Date('1997-10-1 10:10:10')
// iso转换成时间戳
console.log(data*1);
console.log(Number(data));
console.log(data.valueOf());
console.log(data.getTime());
// 时间戳转换回iso
let aa = data *1
console.log(new Date(aa));
// 封装一个时间格式函数
// 思路是,传进去一个格式('yyyy-mm'),然后把格式中对应用来补充的内容的代表词(yyyy mm),来用作为一个key来定义一个对象,每个key对应的内容是用来替换的值
// 然后在循环这个对象,然后把对象里面的内容,和传进去的格式中填充的内容(yyyy mm)进行替换,最后返回这个格式('yyyy-mm'),现在已经变成了一个具体值(2020-10)
let date = new Date()
function dateFormat(date,format = 'yyyy-mm'){
let config = {
yyyy:date.getFullYear(),
mm:date.getMonth()
}
for (let i in config) {
format = format.replace(i,config[i])
}
return format
}
console.log(dateFormat(date)); // 2020-3
// 当传一个参数的时候是创建一个6给位置的为空的数组
let arr = new Array(6) // [ <6 empty items> ]
// 那如果想创建一个元素的数组对象呢
let arr = Array.of(6)
console.log(arr); // 6**
// 判断是否数组
console.log(Array.isArray([])); // true
// 数组转字符串
let aa = [1,2]
console.log(String(aa));
console.log(aa.toString());
console.log(aa.join(','));
// 字符串转数组
let bb = 'abcde'
console.log(bb.split('')); // [ 'a', 'b', 'c', 'd', 'e' ] 把每个拆开来
let cc = 'abcde,ddddd'
console.log(cc.split(',')); // [ 'abcde', 'ddddd' ] 通过逗号拆开
console.log(Array.from(bb)); // [ 'a', 'b', 'c', 'd', 'e' ] 当检测的数据(bb)有length这个属性的时候,就可以使用Array.from
// 比如对象没有length属性,那么使用Array.from会变成空的数组
let obj ={
a:1,
b:2
}
console.log(Array.from(obj)); // []
// 解决,加一个length属性,并且每一个属性的key是正常序列号
let obj1 ={
0:1,
1:2,
length:2
}
console.log(Array.from(obj1)); // [ 1, 2 ]
第二个参数可以遍历整个数组
<div>aaa</div>
<div>bbb</div>
<script>
let divs = document.querySelectorAll('div')
Array.from(divs,function(item){
item.style.color = 'red'
return item
})
console.log(divs); //NodeList(2) [div, div]
// 上面看到是一个dom节点,要是想要用上面的节点数组来使用数组的方法,那么改如何使用
// 就是转换成数组就可以了
// 方法一 Array.from
Array.from(divs).map(item=>{
console.log(item); // 可以得到遍历的两个div对象
})
// 方法二 使用数组原型方法,然后中的map方法,然后执行divs,然后就能拿到
Array.prototype.map.call(divs,function(item){
console.log(item); // 结果和上面一样
})
// 方法三 使用展开,也可以直接变成数组
[...divs].map(item=>{
console.log(item);
})
</script>
let aa = [1,2]
let bb = [2,3]
// 把他们拼接在一个起的简便方法
aa = [...aa,...bb]
<div>aaa</div>
<div>bbb</div>
<script>
let divs = document.querySelectorAll('div')
console.log(divs); //NodeList(2) [div, div]
// 上面看到是一个dom节点,要是想要用上面的节点数组来使用数组的方法,那么改如何使用
// 就是转换成数组就可以了
// 方法一 Array.from
Array.from(divs).map(item=>{
console.log(item); // 可以得到遍历的两个div对象
})
// 方法二 使用数组原型方法,然后中的map方法,然后执行divs,然后就能拿到
Array.prototype.map.call(divs,function(item){
console.log(item); // 结果和上面一样
})
// 方法三 使用展开,也可以直接变成数组
[...divs].map(item=>{
console.log(item);
})
</script>
// pop 删除数组的最后一个元素
// unshift 在数组前面添加一个元素
// shift 删除第一个元素
console.log([1,2,3,4].fill('学习',1,3)) // 表示把从序号1开始,到序号3前面替换成学习
let arr1 = [1,2,3,4]
let arr2 = arr1
arr2 = [] // 此时arr1数组,不为空
// 要实现源数组都清空
arr2.length = 0 // 此时两个数组都为空
// 复制数组内部内容
let arr = [1,2,3,4]
console.log(arr.copyWithin(2,0,2));
// 第一个参数,把复制的内容放到哪里去(序号2开始)。第二个参数,被复制的内容从哪里开始(序号0)。第三个参数,复制几个
// indexOf() 参数是值,是查询在数组中什么位置,返回序列号
// includes() 参数是值,是查询数组中是否有这个值,返回true或false
// find()
let arr = [1,2,3,4]
let res = arr.find(item =>{
// item 1 2 3 4
return item = 2 // 返回匹配内容为true的那一项
}
console.log(res) // 2
)
// findIndex() 是返回匹配内容为true的序列号
// 作用:选取数组中的元素来返回
// 第一个参数是从哪里开始选取
// 第二个参数是选取元素从哪里结束
let a = [1,2,3]
let b = a.slice(0,2) // [1,2] 表示从序号0开始选取,在序号2前面停下来
// every
// 当有一个不符合条件时,返回false
// 有三个参数,value,inde,arr
let a = [1,2,3]
let res = a.every(item=>{
return item >== 2
})
console.log(res) // false 因为里面有一个不符合条件
// some
// 有三个参数,value,inde,arr
// 表示如果有一个元素符合条件就返回true
其实用法和forEach一样,区别在于filter不会改变原来数组,但是forEach会。
并且forEach的return是返回循环一遍的东西
map是对数组进行加工,并且返回一个新数组
// 这样定义的symbol对象,相当于定义了很多个不同的字符串
let a = Symbol()
let b = Symbol()
console.log(a==b); // false
// 给symbol传参数
let c = Symbol('大傻子')
console.log(c.description); // 输出symbol里面的内容
// symbol的for方法定义
let d = Symbol.for('我')
let e = Symbol.for('我')
console.log(d===e); // true 内容一样的时候,使用for定义,可以让这两个变量一样
// 当使用for定义的时候
console.log(Symbol.keyFor(d)); // 我 可以拿到内容
对象中 [ ] 表示引用上面定义的
let user1 = '小明'
// let obj = {
// user1:{name:'aa',age:'bb'}
// }
// console.log(obj); // { user1: { name: 'aa', age: 'bb' } }
let obj = {
[user1]:{name:'aa',age:'bb'}
}
console.log(obj); // { '小明': { name: 'aa', age: 'bb' } }
// let aa ='小明'
// let bb = '小明'
// let obj = {
// [aa]:{name:'aa'},
// [bb]:{name:'bb'}
// }
// console.log(obj); // { '小明': { name: 'bb' } } 会覆盖
let aa ={aa:'小明',key:Symbol()}
let bb = {aa:'小明',key:Symbol()}
let obj = {
[aa.key]:{name:'aa'},
[bb.key]:{name:'bb'}
}
console.log(obj); // { [Symbol()]: { name: 'aa' }, [Symbol()]: { name: 'bb' } }
set
set对象里面可以存放key/value形式的数组
set主要是为了去重,里面不可以存放重复的值
let set = new Set()
set[1] = 'aa'
set[2] = 'bb'
console.log(set); // Set { '1': 'aa', '2': 'bb' }
let obj = {1:'cc'}
let hd = {
[obj]:'小明'
}
console.log(hd[obj.toString()]); // 小明
Set.prototype.add(value) //在Set对象尾部添加一个元素。返回Set对象
Set.prototype.clear() //移除Set对象内的所有元素
Set.prototype.delete(value) //移除Set中与value值相等的元素
Set.prototype.has() //返回一个布尔值,表示该值是否为Set的成员
Set.prototype.keys() //返回键名的遍历器
Set.prototype.values() //返回键值的遍历器
Set.prototype.entries() //返回键值对的遍历器
Set.prototype.forEach() //使用回调函数遍历每个成员
Array.from 方法可以将Set结构转为数组。
或者使用展开语法也可以转换成数组
如数组去重
let a = [1,2,3,2,4,1,3,4]
let b = [...new Set(a)]
console.log(b); // [ 1, 2, 3, 4 ]
// 并集 就是把两个数组放到同一个数组下面,然后放到set里
// 交集 就是拿到两个数组相同的部分
let a = new Set([1,2,3,4])
let b = new Set([2,3,4,5])
// let cc = [1,32,2]
// let qq = cc.filter(item=>{
// return b.has(item) // [2]
// })
console.log(
new Set( [...a].filter(item=>{ // [...a] 变成数组
return b.has(item) // Set { 2, 3, 4 }
}))
);
其实WeakSet和set差不多,包括那些方法
let wset = new WeakSet()
let wset = new WeakSet([1,3]) // 会报错
wset.add([1,3]) // 只能使用这种方式,因为这样是引用[1,3],只能使用引用类型
WeakSet的特性,弱引用类型
// 弱引用类型,什么意思
let a = [1,2,3]
let a = b
// 那么上面就是是 a 和 b 引用了 [1,2,3]
// 然后
let wset = WeakSet()
wset.add(a)
// 此时,内存里wset不会标注引用了 [1,2,3] ,这就是弱引用类型
// 也就是说当 a 和 b 都不引用[1,2,3] 的时候,[1,2,3]就会垃圾回收掉了,但是不会通知到wset ,它还以为自己是有值的
// 然后 过一段时间也会把自己变成空的
// 不能遍历,没有size方法
作用:存储DOM结点,不用担心这些这些节点从文档中删除,引发内存泄露。
内存泄露就是使用强类型的时候,在垃圾回收机制中指挥清理掉内容
let map = new Map()
// 第一种,所有类型都可以用来作为键值
map.set('name','小明')
map.set(function (params) {},'小红')
map.set({},'小绿')
map.set(1,'小蓝')
console.log(map); // Map { 'name' => '小明', [Function] => '小红', {} => '小绿', 1 => '小蓝' }
//并且
let obj = {
name:'小明'
}
let aa = {
[obj]:'小绿'
}
console.log(aa[obj.toString()]); // 小绿
// 第二种
let map = new Map([['aa','a值'],['bb','b值']])
console.log(map); // Map { 'aa' => 'a值', 'bb' => 'b值' }
// 第三种
let map = new Map()
map.set('aa','a值').set('bb','b值')
console.log(map); // Map { 'aa' => 'a值', 'bb' => 'b值' }
// map的一些方法和set差不多
// 比如 has,delect(键值),clear(清除所有),get(键值)根据键值获取值
// map遍历
console.log(map.keys()); // [Map Iterator] { 'name', [Function], {}, 1 }
console.log(map.values()); // [Map Iterator] { '小明', '小红', '小绿', '小蓝' }
console.log(map.entries());
// [Map Entries] {
// [ 'name', '小明' ],
// [ [Function], '小红' ],
// [ {}, '小绿' ],
// [ 1, '小蓝' ]
// }
for (const key of map.keys()) {
console.log(key);
}
for (const value of map.values()) {
console.log(value);
}
for (const [key,value] of map.entries()) {
console.log(key,value);
}
map.forEach((value,key)=>{
console.log(value,key);
// 小明 name
// 小红 [Function]
// 小绿 {}
// 小蓝 1
})
// 第二种遍历
console.log([...map.keys()]);
console.log([...map.values()]);
console.log([...map.entries()]);
// 配合使用filter拿到想拿到的值
let aa = [...map].filter(item=>{
return item.includes('小明')
})
console.log(aa); // [ [ 'name', '小明' ] ]
// 根据字段实现商品的升序降序
let aa = [
{ti:'aa',cli:10,pri:20},
{ti:'bb',cli:374,pri:272},
{ti:'cc',cli:453,pri:8567},
{ti:'dd',cli:43,pri:454653},
]
function order(fild){
return function (a,b){
return a[fild]>b[fild]?1:-1
}
}
let bbb = aa.sort(order('pri'))
console.log(bbb);
// 为何不这样呢
// 原因,sort的回调函数就是传ab来判断的
// 所以,使用闭包的原因就是,通过在函数内部return 函数,来使得回调函数更加的灵活
// function order(fild,a,b){
// return a[fild]>b[fild]?1:-1
// }
// 如平常中我们使用var的时候的for循环,因为定义的是全局变量,所以最后输出的只会是循坏最后的数
// 那么就可以使用闭包来解决这个,那么闭包怎么解决,就在for循环中定义一个立即执行的函数
// 原因就是,每一次调用这个函数,都会生产一个内存空间给它,那么在各自的内存空间中,循坏的值就会保留下来,那么就可以遍历
// 函数里面的定义变量就在函数里面,外部不可用
let divs = document.querySelectorAll('div')
divs.forEach(item=>{
let text = item.getAttribute ('aa')
item.addEventListener('click',function(){
console.log(item); // 能拿到,但此时这个item没有用了,不去除就会造成内存泄露
})
// 解决办法
item = null
})
let obj = {
name:'小明',
age:18
};
delete obj.name
console.log(obj); // { age: 18 }
console.log(obj.hasOwnProperty('age')); //true
// 检测自身原型中有没有当前属性
let arr = [1,2]
console.log('concat' in arr); // true 代表arr的原型中存在concat属性方法
// 设置b为a的原型
let a = {name:'a'}
let b = {name:'b'}
Object.setPrototypeOf(a,b)
console.log(a);
let obj = {
name:'小明',
age:18
}
console.log(
Object.getOwnPropertyDescriptor(obj,'name')
// { value: '小明', writable: true, enumerable: true, configurable: true }
// writable 是否可写,enumerable 遍历,configurable 删除
);
// 获得所有属性的信息
Object.getOwnPropertyDescriptors(obj,null)
// 属性设置
Object.defineProperty(obj,'name',{
value:'大傻逼',
writable:true,
enumerable:true,
configurable:true
})
console.log(obj); // { name: '大傻逼', age: 18 }
// 练习使用reduce,对数据进行处理
let a= [
{name:'小明',age:18},
{name:'小红',age:28},
{name:'小兰',age:18}
]
// let a = [1,2,3,4]
// 以下函数初始化意思是:以{}作为第一个obj,以后每个返回的obj
let res = a.reduce((obj,item,index)=>{
obj[item.age] = item
console.log(obj)
return obj
},{})
console.log(res); // 重复会覆盖 { '18': { name: '小兰', age: 18 }, '28': { name: '小红', age: 28 } }
// 可以使用对象的object.keys()方法或者object.valuse()方法对数组进行,或者使用entries()
let obj = {
name:'小明',
age:18
}
console.log(
Object.getOwnPropertyDescriptors(obj,null)
// { value: '小明', writable: true, enumerable: true, configurable: true }
// writable 是否可写,enumerable 遍历,configurable 删除
);
Object.defineProperty(obj,'name',{
value:'大傻逼',
writable:true,
enumerable:true,
configurable:true
})
console.log(obj); // { name: '大傻逼', age: 18 }