JavaScript 中的数组、对象和解构
本文最后更新于 313 天前,如有失效请评论区留言。

数组

数组很简单,其实没什么好说的,只要了解下常用的API使用就行了

创建数组

js 里有两种创建数组的方式

使用数组字面量创建数组

let myArray = [1, 2, 3, 4, 5];

使用Array构造函数创建数组

let anotherArray = new Array(1, 2, 3, 4, 5);

数组遍历的方法

for 循环:

这种是最基础的写法,没啥好说的

let myArray = [1, 2, 3, 4, 5];

for (let i = 0; i < myArray.length; i++) {
    console.log(myArray[i])
}

forEach 方法:

可以传递一个回调函数作为参数,该函数将在数组的每个元素上调用。这个回调函数可以接受三个参数:当前元素、当前索引和数组本身。

let myArray = [1, 2, 3, 4, 5];

// 使用 forEach 遍历数组
myArray.forEach((element, index, array) => {
    // element: 当前元素的值
    // index: 当前元素的索引
    // array: 原始数组

    // 在这里执行对每个元素的操作
    console.log(`Element at index ${index}: ${element}`);
});

for...of 循环:

for...of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。
element 可被修改,不想被修改就用 const 定义

let myArray = [1, 2, 3, 4, 5];

for (const element of myArray) {
    // 处理每个元素
    console.log(element)
}

map 方法:

遍历数组的每个元素,并对每个元素执行提供的回调函数,最终返回一个新数组,该数组包含对原始数组中的每个元素应用回调函数后的结果。以下是 map 方法的详细用法:

let originalArray = [1, 2, 3, 4, 5];

// 使用 map 遍历数组
let newArray = originalArray.map((element, index, array) => {
    // element: 当前元素的值
    // index: 当前元素的索引
    // array: 原始数组

    // 返回经过回调函数处理后的新值
    return element * 2;
});

// 输出新数组
console.log(newArray); // [2, 4, 6, 8, 10]

filter 方法:

用于遍历数组的每个元素,并根据提供的回调函数的条件,筛选出符合条件的元素,最终返回一个新数组

let originalArray = [1, 2, 3, 4, 5];

// 使用 filter 遍历数组
let filteredArray = originalArray.filter((element, index, array) => {
    // element: 当前元素的值
    // index: 当前元素的索引
    // array: 原始数组

    // 返回一个布尔值,决定是否保留该元素
    return element % 2 === 0; // 保留偶数元素
});

// 输出新数组
console.log(filteredArray); // [2, 4]

reduce 方法:

用于对数组中的所有元素执行一个指定的回调函数(也称为 reducer 函数),并将结果累积到一个最终值。reduce 提供了一种将数组元素合并、累积或转换为单一值的强大机制。

reduce 的回调函数接受四个参数:累加器(accumulator)、当前值(currentValue)、当前索引(currentIndex)、原始数组(array)。在使用 reduce 时,你需要决定如何使用这些参数来实现你想要的逻辑。通常,reduce 在需要对数组进行累积、汇总或转换的情况下非常有用。

数组求和

let numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 15

数组求积

let numbers = [2, 3, 4];
let product = numbers.reduce((accumulator, currentValue) => accumulator * currentValue, 1);
console.log(product); // 24

数组拼接

let words = ["Hello", " ", "World"];
let sentence = words.reduce((accumulator, currentValue) => accumulator + currentValue, "");
console.log(sentence); // "Hello World"

查找最大值:

let values = [10, 5, 8, 15];
let maxValue = values.reduce((max, currentValue) => (currentValue > max ? currentValue : max), values[0]);
console.log(maxValue); // 15

对象数组转换为对象

let data = [
    { key: "a", value: 1 },
    { key: "b", value: 2 },
    { key: "c", value: 3 }
];
let result = data.reduce((obj, item) => {
    obj[item.key] = item.value;
    return obj;
}, {});
console.log(result); // { a: 1, b: 2, c: 3 }

对象

对象是一种无序的键值对集合,其中键是字符串或符号,值可以是任意类型。以下是一些关键的对象操作和概念:

对象的创建

使用对象字面量创建对象

let myObject = { key1: 'value1', key2: 'value2' };

使用Object构造函数创建对象

let anotherObject = new Object({ key1: 'value1', key2: 'value2' });

对象的访问

// 通过点号访问属性
let value = myObject.key1; // 'value1'

// 通过方括号访问属性
let anotherValue = myObject['key2']; // 'value2'

属性定义

const a = "foo";
const b = 42;
const c = {};

const o1 = {
  a: a,
  b: b,
  c: c,
};

// 简写属性名
const o2 = { a, b, c };

console.log(o1.a === o2.a); // true

计算属性名

将一个表达式放在中括号 [] 中,它将被计算并作为属性名使用

const item1 = "name";
const obj1 = {
  [item1]: "Hello",
};
console.log(obj1.name); // "Hello"

const item2 = ["A", "B", "C"];
const obj2 = {
  [item2]: "World",
};
console.log(obj2["A,B,C"]); // "World"

扩展属性

对象字面量支持扩展语法。它将自己提供的对象的枚举属性复制到一个新的对象上。

const obj1 = { foo: "bar", x: 42 };
const obj2 = { foo: "baz", y: 13 };

const clonedObj = { ...obj1 };
console.log(clonedObj.foo, clonedObj.x)

const mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj.foo, mergedObj.x, mergedObj.y)

// 输出
bar 42
baz 42 13

扩展属性可以实现一个对象的拷贝

对象原型

对象原型(Object Prototype)在 JavaScript 中是一个重要的概念,它是构成原型链的基础。原型是每个对象都拥有的一个特殊属性,它指向另一个对象,称为原型对象。通过原型,对象可以继承原型对象上的属性和方法。

在 JavaScript 中,每个对象都有一个原型对象,包括内置对象(如数组、函数等)和自定义对象。对象的原型对象可以通过 __proto__ 属性(不推荐使用)或 Object.getPrototypeOf 方法来获取。

原型的作用主要有以下几点:

  1. 继承属性和方法: 对象通过原型链继承原型对象上的属性和方法。如果对象本身没有某个属性或方法,JavaScript 将在其原型链上查找,直到找到相应的属性或方法,或者到达原型链的末端。

  2. 实现属性和方法的共享: 当多个对象共享同一个原型对象时,它们可以共享原型对象上定义的属性和方法,从而实现一定程度的代码复用。

  3. 构建对象之间的关系: 通过原型链,对象可以与其他对象建立关系,形成对象之间的继承关系。

创建对象原型的方式有如下几种:

使用对象字面量创建原型

name 属性不在对象的原型上,无法通过关键字 __proto__ 获取到原型上的属性

const myPrototype = {
  protoProp: '我是原型上的属性',
};

const myObject = Object.create(myPrototype);
myObject.name = "我是常规属性"

console.log(myObject.protoProp, myObject.name) 
console.log(myObject.__proto__.protoProp) 
console.log(myObject.__proto__.name)

// 输出
> 我是原型上的属性 我是常规属性
> 我是原型上的属性
> 

可以使用 Object.getPrototypeOf 将属性转换为原型上的属性

const prototypeOfMyObject = Object.getPrototypeOf(myObject);
prototypeOfMyObject.name = "转换为对象原型上的属性"
console.log(myObject.__proto__.name)

// 输出
> 转换为对象原型上的属性
使用 Object.setPrototypeOf 方法

Object.setPrototypeOf 方法可以将一个对象设置为另一个对象的原型。

const myPrototype = {
  protoProp: 'I am a property in the prototype'
};

const myObject = {};
Object.setPrototypeOf(myObject, myPrototype);
console.log(myObject.__proto__.protoProp)
使用 ES6 的 class 语法:

类对象 myObject 可以直接获取其构造器上的属性,还可以通过 prototype 来设置原型上的属性

class MyClass {
  constructor() {
    this.constructorProp = '我是构造器上的属性';
  }
}

MyClass.prototype.protoProp = '我是原型上的属性';

const myObject = new MyClass();
console.log(myObject.constructorProp)
console.log(myObject.__proto__.protoProp)
// 输出

> 我是构造器上的属性
> 我是原型上的属性

对象的遍历方式

for...in 循环:

这种方式会遍历对象的所有可枚举属性,包括原型链上的属性。因此,需要使用 hasOwnProperty 进行过滤,以确保只遍历对象自身的属性。

let myObject = { a: 1, b: 2, c: 3 };

for (let key in myObject) {
    console.log(key, myObject[key]);
}

// 输出
a 1
b 2
c 3
for (let key in myObject) {
    if (myObject.hasOwnProperty(key)) {
        console.log(key, myObject[key]);
    }
}

Object.keys 方法:

Object.keys 方法返回一个包含对象所有可枚举属性的数组,然后可以使用数组的遍历方法(如 forEach)来遍历对象的属性。

let myObject = { a: 1, b: 2, c: 3 };

let keys = Object.keys(myObject);

keys.forEach(key => {
    console.log(key, myObject[key]);
});

// 输出
a 1
b 2
c 3

Object.values 方法:

这种只能拿到对象的 value 值

let myObject = { a: 1, b: 2, c: 3 };

let values = Object.values(myObject);

values.forEach(value => {
    console.log(value);
});
// 输出
1
2
3

Object.entries 方法:

返回一个包含对象所有可枚举属性的 [key, value] 对的数组,然后可以使用数组的遍历方法来遍历这些键值对。

let myObject = { a: 1, b: 2, c: 3 };

let entries = Object.entries(myObject);

entries.forEach(([key, value]) => {
    console.log(key, value);
});

// 输出
a 1
b 2
c 3

解构

解构赋值使用类似的语法,但在赋值的左侧定义了要从原变量中取出哪些值。

数组的解构

基本变量赋值

const x = [1, 2, 3, 4, 5];
const [y, z] = x;
console.log(y); // 1
console.log(z); // 2

交换变量

没有解构赋值的情况下,交换两个变量需要一个临时变量,这个很实用啊

let a = 1;
let b = 3;

[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

解析一个从函数返回的数组

这种写法非常的常见,通常函数封装成工具类,可直接解构返回的结果

function f() {
  return [1, 2];
}

const [a, b] = f();
console.log(a); // 1
console.log(b); // 2

忽略某些返回值

使用空值,来表示忽略返回,下面的例子将中间的值忽略不返回

function f() {
  return [1, 2, 3];
}

const [a, , b] = f();
console.log(a); // 1
console.log(b); // 3

const [c] = f();
console.log(c); // 1

对象的解构

基本赋值

const people = {
  name: '张三',
  age: 19,
};

const { name, age } = people;

console.log(name, age); // 张三,19

赋值给新的变量名

可以从对象中提取属性,并将其赋值给名称与对象属性不同的变量。

const people = {
  name: '张三',
  age: 19,
};

const { name:x, age:y } = people;

console.log(x, y); // 张三,19

将 对象中的 name 属性值赋给 x,age 属性赋值给 y

从作为函数参数传递的对象中提取属性

下面这个示例中有一个 user 对象,通过函数来获取 user 的属性 id,参数值 { id } 表示传递给函数的对象的 id 属性应该被提取到一个同名变量中

const user = {
  id: 1001,
  displayName: "jdoe",
  fullName: {
    firstName: "Jane",
    lastName: "Doe",
  },
};

function getUserId({ id }) {
  return id;
}

console.log(getUserId(user)); // 42

获取对象的 displayName,这里可以重新指定提取的属性名称

function userDisplayName({ displayName: dname }) {
  return dname;
}

console.log(userDisplayName(user)); // `jdoe`

嵌套对象属性的提取

function whois({ displayName, fullName: { firstName: name } }) {
  return `${displayName} is ${name}`;
}

console.log(whois(user)); // "jdoe is Jane"

设置函数参数的默认值

默认值可以使用 = 指定,如果指定的属性在传递的对象中不存在,则将其用作变量值。

在 drawChart 的函数签名中,解构的左侧具有空对象 = {} 的默认值。

function drawChart({
  size = "big",
  coords = { x: 0, y: 0 },
  radius = 25,
} = {}) {
  console.log(size, coords, radius);
  // do some chart drawing
}

drawChart({
  coords: { x: 18, y: 30 },
  radius: 30,
});

解构对象时查找原型链

当解构一个对象时,JavaScript 会按照以下规则查找属性:

  1. 直接属性(Own Properties): 首先,JavaScript 会查找对象本身是否具有要解构的属性。如果对象有这个属性,就会从对象本身获取相应的值。

  2. 原型链(Prototype Chain): 如果对象本身没有这个属性,JavaScript 将沿着原型链继续查找。原型链是对象之间的连接,每个对象都有一个指向它的原型对象的链接。如果属性在原型对象中找到,就会返回相应的值。

const obj = {
  self: "123",
  __proto__: {
    prot: "456",
  },
};
const { self, prot } = obj;
console.log(self, prot) // 123 456

obj 的原型对象是 { prot: "456", } ,所以当无法从 obj 属性上找到 prot 属性时,就会去其原型对象上继续寻找 prot 属性

版权声明:除特殊说明,博客文章均为Gavin原创,依据CC BY-SA 4.0许可证进行授权,转载请附上出处链接及本声明。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇