字符串扩展中的使用
展开字符串 字符串转数组
console.log(...'helloworld') // h e l l o w o r l dconsole.log([...'helloworld']) // [ 'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd' ]
数组扩展中的使用
展开数组 解构赋值 复制数组 合并数组
注:如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错
//展开数组
let num = [1, 2, 3]
console.log(...num) //123console.log(...[4, [1, 2, 3], 5]) //每次只能展开一层//解构赋值
let [a, ...rest] = num
console.log(a, rest) //1 [2,3]// 复制数组
let a = [1, 2]
let b = [...a]
console.log(b)// 合并数组
console.log([0, ...[1, 2]])
对象字面量中的扩展
展开对象
数组可以直接扩展 对象扩展需要{}包裹
let obj = { a: 1, b: 2 }
console.log(...obj) // 报错对象需要{}包裹
console.log({ ...obj }) // {a:1,b:2}
合并对象
let foo = { c: 3, ...obj }
console.log(foo) // {c:3,a:1,b:2}
// 等同于let foo = Object.assign(obj, { c: 3 })
扩展在函数中的使用
arguments和...args的区别
结论:arguments 是一个对象,包含所有传入的参数可以通过...arguments获取,而 args 是一个数组,包含所有传入的参数可以通过...args获取
但直接这样写会报错
let [a] = ...arguments //报错
let [b] = ...args //报错
故需要使用在外面包裹一层【】以防止报错
let [a] = [..arguments]
let [b] = [...args]
arguments传入参数为字符串 字面量对象 可使用[...arguments]获取
arguments传入参数为数组 可使用[...arguments][0]获取
...args传入参数为字符串 可使用[...args]获取
...args传入参数为数组 字面量对象 可使用[...args][0]获取
// 结论:arguments 是一个对象,包含所有传入的参数可以通过...arguments获取,而 ...args 是一个数组,包含所有传入的参数
function logArgs1() {console.log(arguments); //[Arguments] { '0': 1, '1': 2 } arguments 是一个对象,包含所有传入的参数console.log([...arguments]) // [ 1, 2 ]console.log(...arguments) // 1 2
}
logArgs1(1, 2)function logArgs2() {console.log(arguments); //[Arguments]{ '0': { a: 1, b: 2 } } arguments 是一个对象,包含所有传入的参数console.log([...arguments]) // [ { a: 1, b: 2 } ]console.log(...arguments) // { a: 1, b: 2 }let [obj] = [...arguments]console.log(obj, obj.a, obj.b) // { a: 1, b: 2 } 1 2
}
logArgs2({ a: 1, b: 2 })
function logArgs3() {console.log(arguments); //[Arguments]{ '0': [ 3, 4 ] } arguments 是一个对象,包含所有传入的参数console.log([...arguments]) //[ [ 3, 4 ] ]console.log(...arguments) // [ 3, 4 ]
}
logArgs3([3, 4])function args1(...args) {console.log(args); //[ 1, 2 ]console.log(...args) // 1 2console.log([...args]) // [ 1, 2 ]}
args1(1, 2)
function args2(...args) {console.log(args); //[ { a: 1, b: 2 } ]console.log(...args) //{ a: 1, b: 2 }console.log([...args]) //[ { a: 1, b: 2 } ]let { a, b } = [...args][0]console.log(a, b) // 1 2}
args2({ a: 1, b: 2 })
function args3(...args) {console.log(args); //[ [ 3, 4 ] ] // args 是一个数组,包含所有传入的参数console.log(...args) //[ 3, 4 ]console.log([...args]) //[ [ 3, 4 ] ]let [a, b] = [...args][0]console.log(a, b) // 3 4
}
args3([3, 4])
使用...args改造普通函数
function sum(a, b, c) {return a + b + c;
}
console.log(sum(1, 2, 3)); // 输出 6function sum1(...args) {let [a, b, c] = args;return a + b + c;
}
console.log(sum1(1, 2, 3));
使用剩余参数与普通参数结合
- 剩余参数只能出现在参数列表的最后。
- 如果没有传入额外的参数,剩余参数将是一个空数组。
- 剩余参数只收集位置参数;关键字参数(比如默认参数、解构参数等)不会被收集。
function greet(first, last, ...messages) {console.log(`Hello ${first} ${last}`); //Hello Alice Doelet [a, b] = [...messages] console.log(a, b) //How are you? Nice to meet you.}
function greet1(first, last, ...messages) {console.log(`Hello ${first} ${last}`); //Hello Alice Doeconsole.log(messages) //[]console.log([...messages])//[]}greet('Alice', 'Doe', 'How are you?', 'Nice to meet you.');
greet1('Alice', 'Doe');
let cameraInfo1 = {id: 0,channelNo: "34020000001320000067",
}let cameraInfo2 = [3, 4]
function getCameraInfo(...args) {let { id, channelNo } = [...args][0]console.log(id, channelNo) // 0 34020000001320000067
}
function getCameraInfo2(...args) {console.log('2==>', args) // 2==> [ [ 3, 4 ], [ 3, 4 ] ]console.log('2==>', args[0], args[1]) //2==> [ 3, 4 ] [ 3, 4 ]
}
getCameraInfo(cameraInfo1)
getCameraInfo2(cameraInfo2, cameraInfo2)
扩展在class类中的使用
类的构造函数(constructor
)中使用剩余参数
let cameraInfo1 = {id: 0,channelNo: "34020000001320000067",
}class Test {constructor(...args) {let { id, channelNo } = args[0]this.id = idthis.channelNo = channelNo}run() {console.log('test1', this.id, this.channelNo)}
}const test = new Test(cameraInfo1)
test.run()
// 输出:
// test1 0 34020000001320000067
类的构造函数(constructor
)中使用默认参数和剩余参数
- 剩余参数必须是构造函数参数列表中的最后一个参数。
- 如果没有提供额外的参数,
hobbies
将会是一个空数组。 - 你可以结合使用默认参数和剩余参数,使得构造函数更加灵活。
class Person {constructor(name, age, ...hobbies) {this.name = name;this.age = age;console.log(hobbies[0])if (Array.isArray([...hobbies][0])) {let [x, y] = hobbies[0]this.x = xthis.y = y} else if (this.isObject(hobbies[0])) {let { x, y } = hobbies[0]this.x = xthis.y = y}}// Object.prototype.toString.call() 方法可以更准确地检测对象类型,因为它会返回一个表示对象类型的字符串,包括内置类型isObject(obj) {return Object.prototype.toString.call(obj) === '[object Object]';}// 如果你只想检测是否是一个数组,可以使用 Array.isArray 方法 Array.isArray(obj)。// 检测对象和数组 obj !== null && typeof obj === 'object' && obj instanceof Objectintroduce() {console.log(`name ${this.name}, age ${this.age},xy ${this.x},${this.y}`);if (this.x) {console.log('xy存在', this.x, this.y)}}
}// 创建一个Person实例
const bob = new Person('Bob', 25);
bob.introduce();
// 输出:
// undefined
// name Bob, age 25,xy undefined,undefinedconst alice = new Person('Alice', 30, { x: 100, y: 200 });
alice.introduce();
// 输出:
// { x: 100, y: 200 }
// name Alice, age 30,xy 100,200
// xy存在 100 200
检测对象
1. 使用 Array.isArray
检测是否是数组
如果你只想检测是否是一个数组,可以使用 Array.isArray
方法。
function isArray(obj) {return Array.isArray(obj);
}console.log(isArray({})); // false
console.log(isArray([])); // true
console.log(isArray(null)); // false
console.log(isArray(42)); // false
console.log(isArray('')); // false
2. 使用 toString
方法检测是否为对象
Object.prototype.toString.call()
方法可以更准确地检测对象类型,因为它会返回一个表示对象类型的字符串,包括内置类型。
function isObject(obj) {return Object.prototype.toString.call(obj) === '[object Object]';
}console.log(isObject({})); // true
console.log(isObject([])); // false
console.log(isObject(null)); // false
console.log(isObject(42)); // false
console.log(isObject('')); // false
3. 结合使用 typeof
和 instanceof
检测对象和数组
为了确保准确性,你也可以结合使用 typeof
和 instanceof
。
function isObject(obj) {return obj !== null && typeof obj === 'object' && obj instanceof Object;
}console.log(isObject({})); // true
console.log(isObject([])); // true
console.log(isObject(null)); // false
console.log(isObject(42)); // false
console.log(isObject('')); // false