一:数组,对象 部分常见方法可以去构造函数部分查看
(1) 数组
数组本质就是一个对象 所以对于一些对象的方法 数组也可以去使用 通过检查数组的类型就会发现数组的类型就是Object
数组的声明方法:
            
            
              javascript
              
              
            
          
          let arr = [1, 2, 3, 4, 5]
let arr1 = new Array(1, 2, 3, 4, 5)//构造函数式声明
        数组常用方法:
            
            
              scss
              
              
            
          
          let arr = [1, 2, 3];
//数组的赋值操作
arr[0] = 1
//将元素添加到数组的尾部 并返回数组的长度
arr.push(4);
//弹出数组末尾元素
arr.pop();
//添加新内容到数组开头 并且返回数组的长度
arr.unshift(0)
//arr.shift 删除第一个元素 
arr.shift()
//arr.splice(起始位置,删除几个元素)
arr.splice(1, 1)
//遍历数组
arr.forEach(item => console.log(item));
//fill填充数组
arr=[];
arr.fill(1) //将数组全部填充为1
//copyWithin复制数组的元素
let hhh=[1,2,3,4,5,6,7,8]
console.log(hhh.copyWithin(4,1,3));//(要粘贴的位置,复制目标的起始位置,复制目标的结束位置(不包括该位置))
        常用方法:
push、pop、shift、unshift、slice、splice、map、filter、reduce
数组解构赋值:
            
            
              scss
              
              
            
          
          //数组解构 将单元直批量赋值给变量的语法  本质是把数组元素赋值给变量
const arr=[100,60,80]
const [max,min,avg]=arr
console.log(max)//100
//交换两个变量
let a=1
let b=0;
[b,a]=[a,b]
console.log(a,b);//1
//剩余参数解决 参数多 变量少问题
const [c,d,...arrr]=[1,2,3,4,5]
console.log(arrr);
//按需解构赋值
const [e,f,,r]=[1,3,4,5]
console.log(r);//5
//多维数组解构
const arr1=[[1,2,3],1]
console.log(arr1[0][0]);// 1
const [t,y]=arr1
        数组的查找方法
数组的查找方法和字符串的查找是一样的 可以理解为字符串本事就是一个字符数组 注意startsWith和endsWith方法不能使用
一些列用于检索的数组方法 const hd=['h','e','i','m','a','c','h','e','g','n','x','v','y','a','u','n']提前定义字符串
- 
indexOf返回字符所在位置 如果找不到就返回-1 从字符串的左边开始查找arduinoconsole.log(hd.indexOf('d'));//返回检索字符所在的位置 找不到的返回负一 从左边开始查找 - 
includes有两个参数 参数一是要查询的位置 参数二是开始查找的位置arduinoconsole.log(hd.includes('h',8));//返回布尔类型 可以设置第二个参数从指定位置开始查找 - 
lastIndexOf返回字符串的位置arduinoconsole.log(hd.lastIndexOf('o'));//从最右边向左开始查找 
数组的迭代器
1.什么是迭代器
迭代器是js中一种特殊的对象,它允许我们按顺序访问数组中的元素,这个迭代器对象是按照迭代器协议创建的next()方法 该方法要求返回一个钓鱼两个属性的对象: value属性(当前迭代的值) done属性(布尔值 表示迭代的状态 是否完成)
2.理解迭代器
可以理解迭代器为一个智能的指针,他知道当前指向哪个元素(value)并且知道当前迭代有没有完成(done)。
3.简单使用迭代器
迭代器工作原理:
            
            
              vbnet
              
              
            
          
          const arr = [1, 2, 3];
// 获取数组的迭代器对象
let iterator = arr.values(); 
// 使用迭代器逐个访问元素
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
        利用迭代器包装的方法:
            
            
              javascript
              
              
            
          
          const arr = [1, 2, 3];
// values() - 返回值的迭代器
for (let value of arr.values()) {
  console.log(value); // 1, 2, 3
}
// keys() - 返回索引的迭代器
for (let key of arr.keys()) {
  console.log(key); // 0, 1, 2
}
// entries() - 返回索引和值的迭代器
for (let [key, value] of arr.entries()) {
  console.log(key, value); // 0 1, 1 2, 2 3
}
        4.迭代器的特点
- 一次性消费: 迭代器只能向前移动,不能后退
 - 惰性计算 : 每次调用 
next方法才会计算下一个值 - 状态保持: 迭代器会记住当前位置
 
(2) 对象
声明对象
1.字面量直接创建:
            
            
              javascript
              
              
            
          
          let person = {
  name: 'Tom',
  age: 18,
  sayHi() {
    console.log('Hi, I am ' + this.name);
  }
}
console.log(person.name);
person.sayHi();
        2.利用js内置方法构造对象
            
            
              javascript
              
              
            
          
          //2.new一个对象创建的是一个空对象   
  const obj2=new Object({name:2})
        3.利用构造函数创建对象
构造函数的本质 :任何函数都可以作为构造函数,通过 new 关键字调用
            
            
              javascript
              
              
            
          
          //构造函数是一种特殊的函数 作用是用来初始化对象的
    function Friden(name,age) {//第一个字母一定是大写开头 只能通过new执行
      this.name=name
      this.age=age
    }
    const yuxuan=new Friden('yuxuan',18)//new的过程就是实例化
    console.log(yuxuan);
        关于使用构造函数创建对象的一些问题
为什么能使用构造函数比如Friden()直接new 一个对象呢,当我们使用 new 关键字调用构造函数时,JavaScript 引擎会创建一个新对象,而构造函数内部使用的 this 就指向这个新创建的对象。因此,在构造函数中通过 this.xxx = xxx 设置的属性确实是直接挂载到这个新对象上的。这个过程在ES6中被直接简化成了语法糖Calss的形势
            
            
              javascript
              
              
            
          
          //使用Class语法糖 是基于原型的构造函数机制
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  sayHello() {
    console.log(`Hello, I'm ${this.name}`);
  }
}
//本质上是一样的是 基于原型的构造函数机制 、
function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.sayHello = function() {
  console.log(`Hello, I'm ${this.name}`);
};
        4.实例属性与静态属性
实例属性:
            
            
              javascript
              
              
            
          
          function Pig(name){
  this.name = name;  // 实例属性
}
const peiqi = new Pig('peiqi');
// name 属性属于实例对象,每个实例都有自己独立的副本
        实例成员:
- 通过 
this.xxx在构造函数内定义 - 每个实例都有自己独立的副本
 - 通过实例对象访问:
instance.property 
静态属性:
静态成员:
- 直接在构造函数上定义:
Constructor.property - 所有实例共享同一份(实际上不属于实例)
 - 只能通过构造函数访问:
Constructor.property 
            
            
              ini
              
              
            
          
          function Person(name) {
  this.name = name;
}
Person.eyes = 2;  // 静态属性
Person.arms = 2;  // 静态属性
// 这些属性直接添加到构造函数本身,而不是实例对象
        原型链关系:
- 实例对象的 
__proto__指向构造函数的prototype - 静态成员不在原型链上,无法通过实例访问,静态成员只是挂载到对象上的,根本就不存在原型链关系
 
对象的基本使用:
            
            
              javascript
              
              
            
          
             let phone = {
      "goods-name": `xiaomi14`,
      money: 4000,
      address: `中国`
    }	
//查找对象的属性
    document.write(phone.address)
    //修改对象属性
    phone.name = `xiaomi15`
    document.write(phone.name)
    //增加对象属性
    phone.color = `白色`
    document.write(phone.color)
    //删除对象属性
    delete phone.money//和c++很像
    document.write(phone.money)//打印是undefind
	//查找对对象
	console.log(phone["goods-name"])
	console.log(phone.money);
	//遍历对象与数组
	for (let key in game) {//key是变量名可以随便取 但是要和后面的game[key]对应
      console.log(game[key])
    }//此方法也可以遍历数组
    let arr = [1, 2, 3, 4, 5]
    for (let k in arr) {
      console.log(arr[k])
    }
        对象的解构赋值:
            
            
              arduino
              
              
            
          
          //解构时属性名和对象名相同
 const{uanme,age}={uanme:'你好',age:18}
 console.log(uanme);
//对象解构变量名更改
const{uanme:username,age:age1}={uanme:'你好',age:19} 
        
            
            
              arduino
              
              
            
          
          //解构数组对象
const pig =[{uname:'佩奇',age:6}]
const[{uname,age}]=pig 
        
            
            
              css
              
              
            
          
          // 多级对象解构
const pig={
  name:'pigs',
  family:{
    mother:'mama',
    father:'baba'
  },
  age:6
}
const {name,family:{mother,father},age}=pig
        二 : 字符串与新增属性
(1) 字符串
1. 字符串转义符
转义符: " \ " 后面没跟需要转义的字符
" 这中间是"一个分号 " 如果我们想打印出这个字符串 中间存在一个" 这就导致不能直接打印出这串字符 这时候需要使用转义符号
            
            
              bash
              
              
            
          
          let str="我是一个 " 分号"
console.log(str);
        2. 字符串拼接与模板字符串,截取,替换
(1)字符串的拼接
拼接字符可以使用+来拼接左右两个字符,或者使用模板字符串。
            
            
              javascript
              
              
            
          
          let obj=[{title:'1'},{title:'2'},{title:'3'}]
function title(){
 return `${
  obj.map((item)=>{
    return `<li>`+item.title+`</li>`
  }).join('')
 }`
}
function title2(){
  return `${obj.map((item)=>{
    return `<li>${item.title}</li>`
  }).join('')}`
}
// 两种写法
        (2)字符串的截取
            
            
              ini
              
              
            
          
          let hd='heimachegnxvyaun'
        字符串的截取有三个方法
- 
slice
- 
slice(从哪开始截取)pythonhd.slice(0) - 
slice(从哪开始截取,到哪停止)pythonhd.slice(0,3) - 
slice(负数)从后面开始算 
pythonhd.slice(-3,-1) - 
 - 
substr 已经被废弃!!!
- 
substr(截取位置)scsshd.substr(0) - 
substr(截取位置,到哪停止)scsshd.substr(0,3) - 
substr(负数没有意义) 
 - 
 - 
substring
- 
substring(截取位置)vbscripthd.substring(0) - 
substring(截取位置,截取个数)vbscripthd.substring(0,3) - 
substring(截取位置,截取个数)vbscripthd.substring(-3,6) 
 - 
 
3. 标签模版
其实就是一个函数 但是存在两个参数 一个是字符串 一个是一个数组
字符串存储的是未填充的字符串 数组存储的是填充的值
            
            
              javascript
              
              
            
          
          function tag(String,...vars){
  // vars 接收所有插值变量组成的数组  所以前一个String是用来存储要被输出的字符串的 然后字符串里面的插入值存在vars里面
  console.log(vars);  // 输出: ["houdenren.com", "后盾人"]
  
  // String 接收模板字符串被插值分割后的部分
  console.log(String); // 输出: ["在线编程网", ",作者", ""]
}
let uname='后盾人'
let web ='houdenren.com'
tag(`在线编程网${web},作者${uname}`);
// 其实主要的作用是对标签中的变量或者字符进行二次处理
        4. 字符串检索
一些列用于在字符串中做检索的字符串方法 const hd='houdunren'提前定义字符串
- 
indexOf返回字符所在位置 如果找不到就返回-1 从字符串的左边开始查找arduinoconsole.log(hd.indexOf('d'));//返回检索字符所在的位置 找不到的返回负一 从左边开始查找 - 
includes有两个参数 参数一是要查询的位置 参数二是开始查找的位置arduinoconsole.log(hd.includes('h',8));//返回布尔类型 可以设置第二个参数从指定位置开始查找 - 
lastIndexOf返回字符串的位置arduinoconsole.log(hd.lastIndexOf('o'));//从最右边向左开始查找 - 
startsWith判断字符是否是字符串的起始值arduinoconsole.log(hd.startsWith('h'));//判断字符串起始值 - 
endsWith判断字符串结束符arduinoconsole.log(hd.endsWith('h'));//判断字符串结束符 
(2)Symbol
Symbol 是 ES6 引入的一种新的原始数据类型,主要用于创建唯一的标识符。可以作为一些属性名的标识符,比如为对象添加唯一的属性名,也可以对属性进行私有化 不让外部来遍历该属性. 可以有效避免属性重名的问题
特点:
- 唯一性 :每个 
Symbol值都是唯一的,即使使用相同的描述创建 - 隐藏性 :
Symbol属性不会出现在常规的遍历中(如for...in或Object.keys) - 不可枚举 :
Symbol属性默认不可枚举,不会被JSON.stringify()序列化 
            
            
              typescript
              
              
            
          
          let symbol = Symbol();
let obj = {
  name: "李四",
  [symbol]: "张三",
};
// 普通遍历遍历不到 symbol 属性
for (let key in obj) {
  console.log(key); //name
}
// 通过for of Reflect.ownKeys()可以遍历到对象里面的 symbol 属性
for (let key of Reflect.ownKeys(obj)) {
  console.log(key);//name Symbol()
}
        属性私有化:
            
            
              javascript
              
              
            
          
          let site = Symbol();
class User {
  constructor(name) {
    this.name = name;
    this[site] = "houdunren";
  }
  getName() {
    return `${this.name} ${this[site]}`;
  }
}
let newuser=new User("lisi")
console.log(newuser.getName()); //lisi houdunren
// 不能获取到symbol属性
for (let key in newuser) {
  console.log(newuser[key]); // lisi
}
        基本用法:
声明symbol变量 访问的时候需要使用symbol变量的description属性来访问
            
            
              ini
              
              
            
          
          // 创建 Symbol
let yf = Symbol("我是逸飞");
console.log(yf); // Symbol(我是逸飞)
console.log(yf.description); // 提取Symbol的描述
// 全局共享的 Symbol
let gs1 = Symbol.for('global');
let gs2 = Symbol.for('global');
console.log(gs1 === gs2); // true
        (3)Set与__WeakSet__
set:
set是一个集合数据类型 和数组相似 但是set中不能存在重复的数据 本质和数组一样是一个引用类型的数据结构
set列表定义及其常见方法:
- 通过set构造函数直接构造set列表对象 可以在构造函数中传入一个数组 初始化set
 - add增加元素
 - delete删除某个具体元素 clear删除全部元素
 - size返回元素个数
 - '...'和数组一样可以展开列表
 - has方法判断某个元素否存在
 
            
            
              csharp
              
              
            
          
          // set是一个集合数据类型 和数组很类似 但是set中不能含有重复的数据
let set =new Set([1,2,3,4,5])
set.add(1);
set.add(1);
set.add(1);
console.log(set);
// 如果定义的时候 set里面是字符串就会把字符串的个字符当作元素
let sets=new Set("hdcms")
console.log(sets);//Set(5) { 'h', 'd', 'c', 'm', 's' }
//增
set.add(1);
set.add(2);
//删
// 单个删除
set.delete(1);
// 清空全部
// set.clear();
// 查询方法
// 查询set里面的元素个数
console.log(set.size); // 2
// 展开语法查看set
console.log([...set]); // [1,2]
// 判断某个元素是否存在,返回布尔类型
console.log(set.has(1)); // true
        set的遍历
            
            
              vbscript
              
              
            
          
          let set=new Set([1,2,3,4,5,6])
set.forEach(function(value,index,set){//使用forEach遍历set
  console.log(value);
})
for (const value of set) {//使用forof遍历set
  console.log(value);
}
        weakset:
weakset和set类型一样都是只能存储唯一值的列表 区别就是weakset是一个弱引用类型的数据结构,并且weakset不能够遍历,并且weakset只能存储对象引用,不能存储基本类型值.
什么是弱引用:
先观察一下set与weakset的区别
Set: 对象即使不再被其他地方引用,只要还在Set中就不会被垃圾回收WeakSet: 对象如果只被WeakSet引用,会被垃圾回收机制自动清理
不难理解出 弱引用就是不用阻止垃圾回收器去回收被weakset引用的对象
如果我们定义一个对象a 分别用不同的变量去引用a 每一次引用都会标记一次引用次数 但是用weakset去引用这个对象就不会添加引用次数 当变量都被清除之后对象a的引用次数也会归零 weakset不会阻止a被垃圾回收
使用示例
            
            
              ini
              
              
            
          
          let nodes=new WeakSet()
let divs=[{div:1},{div:2}]
divs.forEach(element => {
nodes.add(element)
});
console.log(nodes);
//删除 
nodes.delete(divs[0])
console.log(nodes);
//同样使用has判断元素是否存在
console.log(nodes.has(divs[1]));
//weakset不可遍历 并且只能储存对象
        (4)Map与weakMap
Map:
简单理解map
map就是键值对的集合 可以近似理解为用键名代替数组索引的类数组
map类型和obj类型的区别:对象的键只能是字符串类型,map的键名可以是各种类型
声明Map:
- 通过Map构造函数直接构造map变量
 - 使用set方法设置键值对 参数一是键名 参数二是值
 - map的键名可以是任意类型
 
            
            
              c
              
              
            
          
          // 声明Map类型
let map = new Map();
// 键名为字符串 Map方法添加数据不是添加 叫设置数据
map.set("name", "李四");
// 键名为数字
map.set(1, "数字");
// 键名为方法
map.set(function() {}, "方法作为键名");
// 对象键名
map.set({}, "对象键名");
console.log(map);
//或者直接来定义
let map2=new Map([[{},"对象"],[[],'数组'],[function(){},'函数']])
console.log(map2);
        Map的增删改查
- set增
 - delete删除某个具体键值对 clear全部删除
 
            
            
              c
              
              
            
          
          let map = new Map();
// 增
map.set('name','张三')
map.set('age',18)
// 删除
// 单个删除,返回布尔值
console.log(map.delete('age'));
// 全部删除,没有返回值
// map.clear()
// 查询
console.log(map.get('name'));
        遍历Map变量:
- map可以和数组一样进行遍历,也可以使用forEach方法
 - keys方法 返回所有的键
 - values方法 返回所有的值
 - entries方法 返回键值对
 
            
            
              c
              
              
            
          
          let map = new Map();
map.set("name", "李四");
map.set("age", "15");
// 遍历所有的key
console.log(map.keys());//返回所有的键
// 返回所有的值
console.log(map.values());
// 返回值和键
console.log(map.entries());
// for of 遍历键名
for (let key of map.keys()) {
  console.log(key);
}
// for of 遍历值
for (let val of map.values()) {
  console.log(val);
}
// 对象同时接收键和值
for (let [key, val] of map.entries()) {
  console.log(key, val);
}
// forEach 遍历 map,第一个值是键值,第二个值是键名
map.forEach((item, key) => {
  console.log(item, key);
});
        将Map类型转换为数组:
map虽然作为键值对的集合,也可以将键和值单独转换成两个单独的数组 使用展开语法配合不同的方法即可
            
            
              javascript
              
              
            
          
          let hd=new Map([['中文','chinese'],['nihao','hello']])
console.log([...hd]);//将键值对转化为二维数组
console.log([...hd.keys()]);//单独转换键
console.log([...hd.entries()]);//将键值对转化为数组
console.log([...hd.values()]);//将值转化为数组
let newhd=[...hd].filter((item)=>{
  return item[1].includes('chinese')
})
console.log(newhd);
        WeakMap:
WeakMap和Map基本类似,不一样的是WeakMap的键只能是对象,而且不会增加对象的引用. 和WeakSet一样 WeakMap不能遍历 没有size属性 不能cleat直接清除 不能使用foreach方法
常见的使用
验证弱引用特性
            
            
              javascript
              
              
            
          
          let obj={
  name:'list'
}
let weakmap=new WeakMap();
weakmap.set(obj,'houdunren')
// 验证WeakMap中是否有这个键
console.log(weakmap.has(obj));  // 会输出 true
// 获取值
console.log(weakmap.get(obj));  // 会输出 'houdunren'
obj = null;
console.log(weakmap);
setTimeout(() => {
  // 倒计时一秒后再打印结果为空
  console.log(weakmap);
}, 1000);