JavaScript基础知识(三)数组,对象与其他属性

一:数组,对象 部分常见方法可以去构造函数部分查看

(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));//(要粘贴的位置,复制目标的起始位置,复制目标的结束位置(不包括该位置))

常用方法:

pushpopshiftunshiftslicesplicemapfilterreduce

数组解构赋值:

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

数组的查找方法

数组的查找方法和字符串的查找是一样的 可以理解为字符串本事就是一个字符数组 注意startsWithendsWith方法不能使用

一些列用于检索的数组方法 const hd=['h','e','i','m','a','c','h','e','g','n','x','v','y','a','u','n']提前定义字符串

  • indexOf 返回字符所在位置 如果找不到就返回-1 从字符串的左边开始查找

    arduino 复制代码
    console.log(hd.indexOf('d'));//返回检索字符所在的位置 找不到的返回负一 从左边开始查找
  • includes 有两个参数 参数一是要查询的位置 参数二是开始查找的位置

    arduino 复制代码
    console.log(hd.includes('h',8));//返回布尔类型 可以设置第二个参数从指定位置开始查找
  • lastIndexOf返回字符串的位置

    arduino 复制代码
    console.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(从哪开始截取)

      python 复制代码
      hd.slice(0)
    • slice(从哪开始截取,到哪停止)

      python 复制代码
      hd.slice(0,3)
    • slice(负数)从后面开始算

    python 复制代码
    hd.slice(-3,-1)
  • substr 已经被废弃!!!

    • substr(截取位置)

      scss 复制代码
      hd.substr(0)
    • substr(截取位置,到哪停止)

      scss 复制代码
      hd.substr(0,3)
    • substr(负数没有意义)

  • substring

    • substring(截取位置)

      vbscript 复制代码
      hd.substring(0)
    • substring(截取位置,截取个数)

      vbscript 复制代码
      hd.substring(0,3)
    • substring(截取位置,截取个数)

      vbscript 复制代码
      hd.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 从字符串的左边开始查找

    arduino 复制代码
    console.log(hd.indexOf('d'));//返回检索字符所在的位置 找不到的返回负一 从左边开始查找
  • includes 有两个参数 参数一是要查询的位置 参数二是开始查找的位置

    arduino 复制代码
    console.log(hd.includes('h',8));//返回布尔类型 可以设置第二个参数从指定位置开始查找
  • lastIndexOf返回字符串的位置

    arduino 复制代码
    console.log(hd.lastIndexOf('o'));//从最右边向左开始查找
  • startsWith 判断字符是否是字符串的起始值

    arduino 复制代码
    console.log(hd.startsWith('h'));//判断字符串起始值 
  • endsWith判断字符串结束符

    arduino 复制代码
    console.log(hd.endsWith('h'));//判断字符串结束符

(2)Symbol

Symbol 是 ES6 引入的一种新的原始数据类型,主要用于创建唯一的标识符。可以作为一些属性名的标识符,比如为对象添加唯一的属性名,也可以对属性进行私有化 不让外部来遍历该属性. 可以有效避免属性重名的问题

特点:

  1. 唯一性 :每个 Symbol 值都是唯一的,即使使用相同的描述创建
  2. 隐藏性Symbol 属性不会出现在常规的遍历中(如 for...inObject.keys)
  3. 不可枚举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:

WeakMapMap基本类似,不一样的是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);
相关推荐
一枚前端小能手7 小时前
🔁 JavaScript中的迭代全攻略 - for/while/迭代器/生成器/for await...of详解
前端·javascript
拉不动的猪7 小时前
单点登录中权限同步的解决方案及验证策略
前端·javascript·面试
znhy@1237 小时前
十三、JS进阶(二)
开发语言·前端·javascript
Mintopia7 小时前
💰 金融Web应用中的AIGC风险控制技术与合规适配
前端·javascript·aigc
Mintopia7 小时前
🚀 Next.js 压力测试与性能调优实战
前端·javascript·全栈
江城开朗的豌豆7 小时前
TypeScript 类型系统漫游指南:从入门到爱上类型安全
前端·javascript
江城开朗的豌豆7 小时前
从 JavaScript 到 TypeScript:我为什么选择了类型守护
前端·javascript
冷崖8 小时前
QML-Model-View
javascript·c++
蒜香拿铁8 小时前
Angular【核心特性】
前端·javascript·angular.js