Bootstrap

ess之对象拓展、箭头函数、rest 参数、Symbol

目录

1、对象拓展

(1)简写对象

(2)Object.is

(3)Object.assign

(4)setPrototypeOf、getPrototypeOf

2、函数扩展

2.1、箭头函数

(1)语法

(2)箭头函数的特性

补充 this 指向问题汇总

2.2、 参数默认值

(1)形参初始值

(2)与解构赋值结合

(3)这个默认值的方式箭头函数也可以使用

3、rest 参数

4、Symbol

(1)Symbol 基本使用

(2)Symbol 创建对象属性

(3)Symbol 的内置对象


1、对象拓展

ES6 为 JavaScript 的Object对象带来了一系列实用的新方法,这些方法极大地提升了对象操作的便捷性与灵活性,帮助开发者更高效地编写代码。

(1)简写对象

在 ES6 中,允许在对象字面量的大括号内直接写入变量和函数,作为对象的属性和方法。这种写法能够有效减少冗余代码,显著提升代码的可读性与简洁性。

// ES6允许在大括号里直接写入变量和函数,作为对象的属性和方法,书写更简洁

let name = 'bdqn';

let change = function () {

    console.log('我们可以改变你!!');

};

const school = {

    name, // 当属性名和变量名一致时,可直接简写

    change, // 外部定义的函数可直接作为对象属性

    fun: function () {

        console.log("我是复杂写法");

    },

    improve() {

        // 直接在对象里定义函数

        console.log("我是简写");

    }

};

console.log(school);

注意:在后续开发中,建议优先采用这种简洁的对象简写形式。它不仅能提高代码编写效率,还能增强代码的可维护性。例如在构建配置对象时,使用简写形式会让代码更加清晰易读 。

(2)Object.is

Object.is()方法用于判断两个值是否严格相等,其行为与===运算符基本一致,但在处理+0NaN时存在差异。

console.log(Object.is(120, 120)); // true,与 === 行为一致

console.log(Object.is(NaN, NaN)); // true,NaN 与自身严格相等

console.log(NaN === NaN); // false,=== 认为 NaN 与自身不相等

在实际应用中,当需要精确判断两个值是否完全相等,尤其是涉及NaN等特殊值时,Object.is()方法能提供更准确的结果。

(3)Object.assign

Object.assign()方法用于合并对象,它会将源对象的所有可枚举属性复制到目标对象中。如果存在相同属性,后面源对象的属性会覆盖目标对象的属性。

Object.assign(target, object1, object2);
  • target:合并后存放属性的目标对象。
  • object1:第一个源对象。
  • object2:第二个源对象,可根据需要添加更多源对象。
const obj1 = {

    name: "tom",

    age: 18

};

const obj2 = {

    name: "bob",

    age: 28,

    sex: "男"

};

console.log(Object.assign(obj1, obj2));

// {name: 'bob', age: 28, sex: '男'},obj2 的属性覆盖了 obj1 中相同的属性

在合并配置对象、继承属性等场景下,Object.assign()方法非常实用,能够简化代码逻辑。

(4)setPrototypeOf、getPrototypeOf

Object.setPrototypeOf()Object.getPrototypeOf()方法可直接设置和获取对象的原型。不过,由于原型链操作可能引发性能问题和代码复杂度增加,通常不建议频繁使用。

// 设置原型

Object.setPrototypeOf(school, cities);

// 参数1:给谁设置原型对象 school

// 参数2:设置哪个原型对象 cities

// 获取原型

Object.getPrototypeOf(school);
const school = {

    name: "bdqn"

};

const cities = {

    xiaoqu: ["北京", "上海", "深圳"]

};

// 设置原型

Object.setPrototypeOf(school, cities);

// 获取原型

Object.getPrototypeOf(school);

console.log(school);

在某些特定的面向对象编程场景中,如实现对象的继承体系时,可能会用到这两个方法,但需要谨慎操作,确保代码的性能和可读性。

2、函数扩展

2.1、箭头函数

ES6 引入了箭头函数(=>)来定义函数,这种函数表达式更加简洁。不过,箭头函数只能用于简写函数表达式,无法简写声明式函数。

function fn() {} // 不能用箭头函数简写

const fun = function () {}; // 可以简写为箭头函数

const obj = {

    fn: function () {} // 可以简写为箭头函数

};
(1)语法

() => {}

  • ():用于定义函数的参数,若有多个参数,用逗号分隔。
  • =>:箭头函数的标志性语法,用于连接参数和函数体。
  • {}:函数体,包含具体的执行逻辑。
// ES6允许使用箭头(=>)定义函数

// 声明一个函数

// let fn = function(){}

// 等价于

let fn = (a, b) => {

    return a + b;

};

// 调用函数

let result = fn(1, 2);

console.log(result);
(2)箭头函数的特性
  • this 是静态的:箭头函数中的this始终指向函数声明时所在作用域下的this值,它自身没有独立的this绑定。
  • 不能作为构造实例化对象:尝试使用new关键字调用箭头函数会导致报错,因为箭头函数没有prototype属性。
  • 不能使用 arguments 变量:箭头函数没有自己的arguments对象,若要访问函数参数,可使用命名参数或rest参数。
  • 箭头函数的简写
    • 省略小括号:当形参有且仅有一个时,可省略参数的小括号。
    • 省略花括号:当函数体只有一条语句时,可省略花括号,此时return关键字也需省略,语句的执行结果将自动作为函数的返回值。
// 箭头函数的特性

// 1. this 是静态的,this 始终指向函数声明时所在作用域下的 this 值,没有自己的 this

function getName() {

    console.log(this.name);

}

let getName2 = () => {

    console.log(this.name);

};

// 设置 window 对象的 name 属性

window.name = "北大青鸟";

const school = {

    name: "bdqn"

};

// 直接调用,this指向window

// getName();

// getName2();

// call 方法调用

// getName.call(school);  // 指向school

// getName2.call(school);  // 指向window

// 2. 不能作为构造实例化对象,会报错

// let Person = (name, age) => {

//     this.name = name;

//     this.age = age;

// };

// let me = new Person('xiao', 30);

// console.log(me);

// 3. 不能使用 arguments 变量

// let fn = () => {

//     console.log(arguments);

// };

// fn(1, 2, 3);

// 4. 箭头函数的简写

// 1) 省略小括号,当形参有且只有一个的时候

let add = n => {

    return n + n;

};

console.log(add(9));

// 2) 省略花括号,当代码体只有一条语句的时候,此时 return 必须省略,而且语句的执行结果就是函数的返回值

let pow = (n) => n * n;

console.log(pow(8));

注意:箭头函数不会改变this的指向,在需要保持this一致性的回调函数场景中,如事件处理函数、数组的迭代方法回调等,箭头函数是非常合适的选择。在实际应用中,应根据具体需求合理使用箭头函数,以充分发挥其简洁性和便利性。

补充 this 指向问题汇总
  • 作为普通函数被调用时this指向全局对象window(在浏览器环境中)或global(在 Node.js 环境中)。
window.age = 18;

function fn() {

    console.log(this.age); // 18

}

fn();
  • 对象方法里的 this:当函数作为对象的方法被调用时,this指向该对象本身。
var obj = {

    age: 18,

    fn: function () {

        console.log(this === obj); // true

        console.log(this.age); // 18

    }

};

console.log(obj.fn());
  • 构造函数里面的 this:在构造函数中,若没有return语句或return的是基本数据类型,this指向new创建的实例化对象;若return的是一个object对象,则最终返回该对象。
function Fn() {

    this.age = 18;

    // 此时a.age是return的结果20

    return {

        age: 20

    };

}

let a = new Fn();

console.log(a.age); // 20
  • call、apply、bind:在function的原型上有callapplybind三个方法,所有函数都是Function的实例,均可调用这三个方法来改变this的指向。
// 定义:call(thisObj,Object) 调用一个对象的一个方法,以另一个对象替换当前对象。

// 说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

function fn(x, y) {

    console.log('加油');

    console.log(this); // this指向window

    console.log(x + y);

}

var o = {

    name: 'andy'

};

fn.call(); // call 呼叫 可以调用函数

fn.call(o, 1, 2); // 第一个值是this指向,后边实参

fn.apply(o, [10, 20]); // apply传递数组

fn.call(10, 20); // this-->new Numbe(10) x-->20 y-->undefined
  • 箭头函数中 this:箭头函数没有自己独立的this,它会从自己的作用域链上一层继承this
this.age = 20;

var obj = {

    age: 18,

    fn: () => {

        console.log(this.age); // 20

    }

};

obj.fn();
2.2、 参数默认值
(1)形参初始值

在定义函数时,具有默认值的参数通常建议放在参数列表的末尾。这是一种潜规则,能避免参数解析时的混淆,提高代码的可读性和可维护性。

function add(a, b, c = 10) {

    return a + b + c;

}

// let res1 = add(1, 2, 3); // 6

let res2 = add(1, 1);

console.log(res2); // 12
(2)与解构赋值结合

参数默认值可以与解构赋值一起使用,使函数参数的传递和处理更加灵活。

function connect({ name, age, sex, price = "3000" }) {

    console.log(name);

    console.log(age);

    console.log(sex);

    console.log(price);

}

connect({

    name: "章三",

    age: 20,

    sex: "男"

    // price: 4000,

});
(3)这个默认值的方式箭头函数也可以使用

箭头函数同样支持参数默认值的设置,为函数的定义和调用提供了更多便利。

const fn = (a = 10) => {

    console.log(a);

};

fn(); // 不传递参数的时候,函数内部的 a 就是 10

fn(20); // 传递了参数 20 的时候,函数内部的 a 就是 20

注意:在使用箭头函数的参数默认值时,如果只有一个参数,也需要保留小括号,以确保语法的正确性。在实际编写函数时,合理设置参数默认值能提高函数的通用性和易用性,减少不必要的参数传递。

3、rest 参数

ES6 引入了rest参数,用于获取函数的实参列表,它可以替代传统的arguments对象。rest参数必须放在函数参数列表的最后。

// ES5 获取实参的方式

// function date(){

//     console.log(arguments);

// }

// date('大白','二黑','三孩');

// rest 参数

function date(...args) {

    console.log(args); // filter some every map

}

date("大白", "二黑", "三孩");

// rest 参数必须要放到参数最后

function fn(a, b,...args) {

    console.log(a);

    console.log(b);

    console.log(args);

}

fn(1, 2, 3, 4, 5, 6);

注意rest参数在处理不定个数参数的函数场景中非常实用,它将所有剩余参数收集到一个数组中,方便进行统一处理。例如在编写日志记录函数、函数柯里化等场景中,rest参数能使代码更加简洁和灵活。在实际开发中,当遇到需要处理不定数量参数的情况时,优先考虑使用rest参数能有效提升代码的质量和可维护性。

4、Symbol

(1)Symbol 基本使用

ES6 引入了一种新的原始数据类型Symbol,它表示独一无二的值。Symbol是 JavaScript 语言的第七种数据类型,类似于字符串,但具有唯一性。

// 创建方式

// 创建Symbol方式1

let s = Symbol();

// console.log(s, typeof s);

// 创建方式2

// Symbol()函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,比较容易区分

let s2 = Symbol('bdqn'); // 'bdqn'这个内容只是个标识

let s3 = Symbol('bdqn');

console.log('s2===s3', s2 === s3); // false

// 创建方式3  Symbol.for

// Symbol.for并不是每次都会创建一个新的symbol,它会先检索symbol表中是否有,没有再创建新的,有就返回上次存储的

let s4 = Symbol.for('bdqn');

let s5 = Symbol.for('bdqn');

console.log('s4===s5', s4 === s5); // true

// 注意事项

// 1: 不能与其他数据进行运算

try {

    let result = s + 100;

} catch (error) {

    console.error('Symbol值不能与其他数据进行运算,错误信息:', error.message);

}
(2)Symbol 创建对象属性

Symbol可以用于为对象添加唯一的属性和方法,避免属性名冲突。

// 向对象中添加方法 up down

let game = {

    name: "俄罗斯方块",

    up: function () {},

    down: function () {}

};

// 声明一个对象

let methods = {

    up: Symbol(),

    down: Symbol()

};

game[methods.up] = function () {

    console.log("我可以改变形状");

};

game[methods.down] = function () {

    console.log("我可以快速下降!!");

};

console.log(game);
(3)Symbol 的内置对象

除了自定义的Symbol值,ES6 还提供了 11 个内置的Symbol值,它们指向语言内部使用的方法,这些方法在特定场景下会自动执行,也被称为魔术方法。

Symbol 属性

描述

Symbol.hasInstance

当其他对象使用instanceof运算符判断是否为该对象的实例时,会调用这个方法

Symbol.isConcatSpreadable

对象的Symbol.isConcatSpreadable属性是一个布尔值,决定该对象在使用Array.prototype.concat()时是否可以展开

Symbol.species

创建衍生对象时,会使用该属性来指定构造函数

Symbol.match

当执行str.match(myObject)时,如果该属性存在,会调用它并返回该方法的返回值

Symbol.replace

当该对象被str.replace(myObject)方法调用时,会返回该方法的返回值

Symbol.search

当该对象被str.search(myObject)方法调用时,会返回该方法的返回值

Symbol.split

当该对象被str.split(myObject)方法调用时,会返回该方法的返回值

Symbol.iterator

对象进行for...of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器

Symbol.toPrimitive

该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值

Symbol.toStringTag

在该对象上面调用toString方法时,返回该方法的返回值,用于自定义对象的字符串表示

Symbol.unscopables

该对象指定了使用with关键字时,哪些

;