JS补充1

Object.freeze() 冻结对象

    let obj={
      a:99,
      name:'小明'
    };
    Object.freeze(obj)
    obj.a = 100  
    console.log( obj);   // /输出99,因为冻结之后对象的内容无法改变

Object.keys()

// 获取对象key值

null,undefind的使用

// 定义默认值的时候
let a = null; // 代表定义的是引用类型
let b = undefind; // 代表定义的是基本类型 

字符串方法slice、substring、substr、repeat()

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)) // *****

indexOf

let aa = 'abcd'
// 如果存在这个字符就会返回这个字符的序号,如果不存在就会返回-1
// 第二个参数代表从第几个开始查找
console.log(aa.indexOf('a',2)) // -1

includes

let aa = 'abcd'
// 如果存在这个字符就会返回true,如果不存在就会返回false
// 第二个参数代表从第几个开始查找
console.log(aa.includes('a',2)) // false

startWith、endsWith

// 检测该字符串的开头是不是这个字符
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
     

Number基本函数之isSafeInteger、toFixed

let aa = 100.33;
// 检测是不是int类型
console.log(Number.isSafeInteger(aa)); // false

// 加载到小数点后几位
console.log(aa.toFixed(1)); // 100.3

math的一下函数

// 正常使用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));

Date()时间的一下函数

// 检测脚本时间
// 方法一
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

constd定义的数组里面的值可以改变的

Array.of()方法的使用

// 当传一个参数的时候是创建一个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' ] 通过逗号拆开

Array.from()

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 ]

Array.from()的一个好用处

第二个参数可以遍历整个数组

  <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>

数组方法之fill()

// 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和includesOf和find()和findIndex()的使用

// 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的序列号

数组中的slice()

// 作用:选取数组中的元素来返回
// 第一个参数是从哪里开始选取
// 第二个参数是选取元素从哪里结束
let a = [1,2,3]
let b = a.slice(0,2)  // [1,2] 表示从序号0开始选取,在序号2前面停下来

数组中every和some

// 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

数组对象中filter过滤元素的使用

其实用法和forEach一样,区别在于filter不会改变原来数组,但是forEach会。
并且forEach的return是返回循环一遍的东西
map是对数组进行加工,并且返回一个新数组

Symbol

// 这样定义的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)); // 我 可以拿到内容

Symbol的使用

对象中 [ ] 表示引用上面定义的

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和map对象(类似数组)

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实现并集交集算法

// 并集 就是把两个数组放到同一个数组下面,然后放到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的使用

其实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结点,不用担心这些这些节点从文档中删除,引发内存泄露。
内存泄露就是使用强类型的时候,在垃圾回收机制中指挥清理掉内容

map对象

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);

JS补充1_第1张图片

其实工厂函数的本质就是封装函数,实现多复用

实现对对象的属性进行可控制(可否删除遍历修改)

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结合数组对象的使用

// 练习使用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.assign(obj1,obj2) 合并两个对象,生成一个新的对象
for in遍历对象 for of遍历数组
for of遍历对象的方法
// 可以使用对象的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 }

你可能感兴趣的:(JS)