第四章 ES6

内容来源于蓝桥杯竞赛,自己根据这个题纲重新巩固下前端的知识

第四章 ES6

它是 2015 年发布的一个 JavaScript 版本,被命名为 ECMAScript 2015,也叫 ECMAScript 6,故简称为 ES6。实现写更少的代码,做更多的事情

新增关键字

var 关键字的缺点
变量提升机制的问题

在 JavaScript 中有一个提升机制,就是无论你在哪里使用 var 关键字声明变量,它都会被提升到当前作用域的顶部。

变量重复声明的问题

var 关键字声明的变量可以重复赋值,在实际开发中遇到switch cash 定义同一个变量名时,var可以实现该功能。

非块作用域的问题

var不属于块作用域,for循环中它会将结果带到for循环外即变量提升机制。

认识 let 关键字
解决变量提升机制问题

它可以解决变量定义只存在块之间的问题

解决变量重复声明的问题

虽然 let 关键字声明的变量可以重新赋值,但是它与 var 关键字有所不同,let 关键字不能在同一作用域内重新声明,而 var 可以。

解决非块级作用域的问题
认识 const 关键字

const用于声明一个只读的常量且一旦声明,常量的值就不能改变。如果你尝试反复赋值的话,则会引发错误。

值类型
引用类型

就是定义一个数组,这里突然想到一个深拷贝浅拷贝的问题浅拷贝与深拷贝的区别可以学习下,简单来说浅拷贝可以用Object.assign()实现,深拷贝可以用JSON.parse(JSON.stringify())实现。

字符串的扩展

模板字面量

就是``这个符号,当你应用的str中包含该符号时间可以用\转义

这个模板字面量可以用来实现打印多行输出,但是用一个问题定义在反撇号中的字符串,其中的空格、缩紧、换行都会被保留。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      let str = `Hello,
        ECMAScript 6`;
      console.log(str);
    </script>
  </body>
</html>

在这里插入图片描述

字符串的占位符
let str = `LanQiao Courses`;
let message = `I like ${str}.`;
console.log(message);
// 还支持输入表达式
let a = 2;
let b = 1;
let sum = `a+b=${a + b}`;
console.log(sum);
—标签模板

这里的标签并不是在 HTML 中所说的标签,这里的标签相当于是一个函数。而标签模板就是执行模板字面量上的转换并返回最终的字符串。

let name = `JavaScript`;
let str = tag`Welcome to ${name} course.`; // 这里的tag是自定义的函数
  • 第一个参数是一个数组,数组中存放普通的字符串,例如 str 中的 Welcometocourse.

  • 在第一个参数之后的参数,都是每一个占位符的解释值,例如 str 中的 ${name}

    function tag(literals, ...values) {
      let result = ""; // result 变量用来存放重组后的数组
      // 根据 values 的数量来确定遍历的次数
      for (let i = 0; i < values.length; i++) {
        result += literals[i];
        result += values[i];
      }
      // 合并最后一个 literals
      result += literals[literals.length - 1];
      return result;
    }
    let name = `JavaScript`;
    let str = tag`Welcome to ${name} course.`;
    console.log(str);
    
  • 作用

    • 过滤 HTML 字符串,防止用户输入恶意内容。
    • 多语言的转换。
字符串的新增方法
  • includes():判断是否包含指定字符串,如果包含返回 true,反之 false。
  • startsWith():判断当前字符串是否以指定的子字符串开头,如果是则返回 true,反之 false。
  • endsWith():判断当前字符串是否以指定的子字符串结尾,如果是则返回 true,反之 false。
repeat()

repeat(n) 方法用于返回一个重复 n 次原字符串的新字符串,其参数 n 为整数,如果设置 n 为小数,会自动转换为整数。

replaceAll()

在 ES6 中,为我们提供了 replaceAll() 方法来解决这个问题,它可以用来替换所有匹配的字符串。

let str = "HELLOWHELLOWHELLO";
console.log(str.replaceAll("W", "_"));

数组的扩展

创建数组的方法
Array.of()
let arr = new Array(4, "7", "8");
console.log("数组长度:" + arr.length);
console.log("arr[0]:" + arr[0]);
console.log("arr[1]:" + arr[1]);
console.log("arr[2]:" + arr[2]);

用上面这样的方式传入值是存在一定风险的。Array.of() 为我们解决了这个问题。我们来看看它是怎么用的。👻这里他说之前的方法有风险,但是风险是啥呢?可能就是???

Array.of(element 0, element 1, ..., element N)
Array.from()

可以实现把类似数组的对象转为数组。之前是通过[].slice.call()现在可通过Array.from

数组实例的方法
find()

find() 方法是用于从数组中寻找一个符合指定条件的值,该方法返回的是第一个符合条件的元素,如果没找到,则返回 undefined.

array.find(callback(value, index, arr), thisValue);
  • callback 是数组中每个元素执行的回调函数。
  • value 是当前元素的值,它是一个必须参数。
  • index 是数组元素的下标,它是一个可选参数。
  • arr 是被 find() 方法操作的数组,它是一个可选参数。
  • thisValue 是执行回调时用作 this 的对象,它是一个可选参数。
let arr = [1, 3, 4, 5];
arr.find(function (value, index, arr) {
  console.log(value > 2);
  console.log(index);
  console.log(arr);
});

它是先把所有的都遍历完之后返回第一个满足条件的值
findIndex()

findIndex() 方法返回数组中第一个符合指定条件的元素的索引下标值,如果整个数组没有符合条件的元素,则返回 -1。

array.findIndex(callback(value, index, arr), thisArg);
  • callback 是数组中每个元素都会执行的回调函数。
  • value 是当前元素的值,它是一个必须参数。
  • index 是数组元素的下标,它是一个必须参数。
  • arr 是被 findIndex() 方法操作的数组,它是一个必须参数。
  • thisArg 是执行回调时用作 this 的对象,它是一个可选参数。
let arr = ["小猫", "小狗", "兔子"];
arr.findIndex(function (value, index, arr) {
  console.log(value == "兔子");
  console.log(`${value}是数组中的第 ${index + 1} 位。`);
});
fill()

fill() 方法是用指定的值来填充原始数组的元素。

array.fill(value, start, end);
  • value 是用来填充数组的值,它是一个必须参数。
  • start 是被填充数组的索引起始值,它是一个可选参数。
  • end 是被填充数组的索引结束值,它是一个可选参数。
let arr = ["🐱", "🐶", "🐰", "🐍", "🐦", "🐟"];
let result = arr.fill("🐷", 2, 5); //如果不指定起始和结束位置会替换掉所有的
console.log(result);

以下是 ES6 中三种数组的遍历方法,三个方法返回的都是 Array Iterator 对象。但三者之间肯定不是完全相同的,接下来我们一一学习。

entries()

entries() 方法以键/值对的形式返回数组的 [index,value],也就是索引和值。其语法格式为:

let arr = ["🐱", "🐶", "🐰", "🐍", "🐦", "🐟"];
let result = arr.entries();
console.log(...result);
keys()

keys() 方法只返回数组元素的键值也就是元素对应的索引,不会返回其值。

let arr = ["🐱", "🐶", "🐰", "🐍", "🐦", "🐟"];
let result = arr.keys();
console.log(result);
console.log(...result);
values()

values() 方法返回的是每个键对应的值。

for…of 循环

for...of 就摆脱了计数器、退出条件等烦恼,它是通过迭代对象的值来循环的。它能迭代的数据结构很多,数组、字符串、列表等。但在本实验中我们重点放在数组的遍历上。

for (variable of iterable) {}
  • variable:是存放当前迭代对象值的变量,该变量能用 constletvar 关键字来声明。
  • iterable:是可迭代对象。
let str = "hello";
for (let item of str) {
  console.log(item);
}
扩展运算符

扩展运算符(…)是 ES6 的新语法,它可以将可迭代对象的参数在语法层面上进行展开。

数组上
// 向数组添加值
let animals = ["兔子🐰", "猫咪🐱"];
let zoo = [...animal, "老虎🐯", "乌龟🐢", "鱼🐟"];
console.log(zoo);
// 复制数组
let animals = ["老虎🐯", "乌龟🐢", "鱼🐟"];
let newAnimals = [...animals];
console.log(newAnimals);
对象上

在对象上,我们主要有以下三种操作:

  • 可以使用扩展运算符将一个对象的全部属性插入到另一个对象中,来创建一个新的对象。
  • 可以使用扩展运算符给对象添加属性。
  • 可以使用扩展运算符合并两个新对象。
// 合并对象
let studentName = { name: "小白" };
let studentAge = { age: 17 };
let NewObj = { ...studentName, ...studentAge };
console.log(NewObj);

函数的扩展

默认参数
function func(words, name = "🍎") {
  console.log(words, name);
}
func("请给我一个");
func("请给我一个", "🍐");
func("请给我一个", "");
// 传一个函数
function add(a = 5) {
  let result = 0;
  for (let i = 1; i <= a; i++) {
    result += i;
  }
  return result;
}
console.log("1~5 相加的和为:", add());
console.log("1~10 相加的和为:", add(10));
//解构参数
function func(name, value, mount, { a, b, c, d = "苹果" }) {
  console.log(`${name}${value}元钱买了${mount}${d}`);
  console.log(`${name}${value}元钱买了${mount}${c}`);
}
func("小蓝", 5, 3, {
  a: "西瓜",
  b: "菠萝",
  c: "桃子",
});
rest 参数

rest 参数又称为剩余参数,用于获取函数的多余参数。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

// 剩余参数必须是函数的最后一个参数
myfunction(parameters, ...rest);
function func(a, b, ...rest) {
  console.log(rest);
}
func(1, 2, 3, 4, 5, 6, 7, 8, 10); // 输出 3 4 5 6 7 8 9 10
箭头函数

箭头函数,顾名思义,就是用箭头(=>)来表示函数。箭头函数和普通函数都是用来定义函数的,但两者在语法构成上非常不同。箭头函数除了代码简洁以外,它还解决了匿名函数的 this 指向问题。

  • 箭头函数的 this 指向是其上下文的 this,没有方法可以改变其指向。
  • 普通函数的 this 指向调用它的那个对象。

类的扩展

类的声明
// ES5 语法
function DogType(name) {
  this.name = name;
}
DogType.prototype.sayName = function () {
  console.log("大家好!我是一只小" + this.name + "。");
};
let dog = new DogType("柯基");
dog.sayName();
console.log(dog instanceof DogType);
console.log(dog instanceof Object);

// ES6 语法
let DogType = class {
  constructor(name) {
    this.name = name;
  }
  sayName() {
    console.log(`大家好!我是一只小${this.name}`);
  }
};
let dog = new DogType("柯基");
dog.sayName();
console.log(dog instanceof DogType);
console.log(dog instanceof Object);
类的继承
class Animal {
  constructor(name, age, speed) {
    this.name = name;
    this.age = age;
    this.speed = speed;
  }
  run() {
    console.log(`${this.age}岁的${this.name}酷跑了 ${this.speed} 公里。`);
  }
  stop() {
    console.log(`${this.name}停止了奔跑。`);
  }
}
class Dog extends Animal {} // Dog 类继承了 Animal 类
// 实例化 Dog 类
let dog = new Dog("闷墩儿", "一", 5);
// 调用 Animal 类中的 run() 方法和 stop() 方法
dog.run();
dog.stop();
类的属性和方法
  • 静态方法
  • 静态属性
  • 私有方法
  • 私有属性
new.target 属性

对象的扩展

对象字面量

对象字面量就是使用 {} 去定义对象。

const name = "闷墩儿";
const age = 2;
const dog = { name: name, age: age };
// 9优化后
const dog = { name, age };
对象的扩展运算符

在对象中引入扩展运算符后,我们可以用来遍历参数对象中的所有属性,并将其拷贝到新对象中。

let obj1 = { species: "柯基", name: "闷墩儿", age: 2 };
let obj2 = { ...obj1 };
console.log(obj2);
对象的新增方法
Object.is
console.log(Object.is(-0, +0)); // false
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(7 == "7")); // false
Object.assign

在 ES6 之前对象组合中我们往往会用到 mixin() 方法,其方法的作用就是一个对象接受另一个对象的属性和方法。

在 ES6 中引入了 Object.assign 来合并对象,该方法一个对象可以接受任意多个对象的属性和方法,我们来看个例子。

遍历对象
对象的扩展运算符
对象的新增方法

Set 和 Map

Set 与数组之间的区别:

  • Set 是一个可以存储数据的对象,你可以在其中添加或者删除数据,并循环访问 Set。但是 Set 中没有索引,也不能存放重复的值,数组与之相反。

Set 与 WeakSet 的区别:

  • Set 是强引用,创建的对象不能被垃圾回收,WeakSet 是弱引用,创建的对象可以被垃圾回收。

Map 对象:

  • Map 可以创建任意数据类型的键值对,打破了对象键名类型限制的局限性。
  • 我们可以使用 forEach() 方法来遍历 Map,而对象不能。
  • 我们可以使用 set()get()has()delete()clear() 等方法来操作 Map。

异步编程

Promise 对象基础应用
地狱式回调

通过接口 1 的返回值,去获取接口 2 的数据,然后,再通过接口 2 的返回值,获取接口 3 的数据。即每次请求接口数据时,都需要使用上一次的返回值。为了实现这个需求,通常会使用回调函数来完成,即把函数作为参数进行层层嵌套。其实现代码如下:

var outnum = function (n, callback) {
  setTimeout(function () {
    console.log(n);
    callback();
  }, 1000);
};
outnum("1", function () {
  outnum("2", function () {
    outnum("3", function () {
      console.log("0");
    });
  });
});
定义 Promise 对象

为了解决这种地狱式的回调,可以使用 Promise 对象,且代码更优雅,由于 Promise 对象是一个构造函数,因此,必须通过实例化来生成,它的定义格式如下代码:

let p = new Promise(function (resolve, reject) {
  // 此处做一个异步的事情
});
  • 在实例化中,参数为函数,函数中又有两个用于回调的函数。
  • 两个回调函数中,resolve 为异步执行成功时的回调,其参数可以传递执行的结果。
  • reject 为异步执行失败时的回调,其参数可以传递失败的错误信息。
Promise 对象的 then 方法
let n = 6;
let p2 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    if (n > 5) {
      resolve(n);
    } else {
      reject("必须大于5");
    }
  });
});
p2.then(
  function (v) {  // v 值表示 resolve 回调函数中的参数值
    console.log(v);
  },
  function (e) {
    console.log(e);// e 值表示 reject 回调函数中的参数值
  }
);
// 执行代码后,由于 n 值大于 5 ,因此,在控制台中输出数字 6 。
解决地狱式回调
var outnum = function (order) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      console.log(order);
      resolve();
    }, 1000);
  });
};
outnum("1")
  .then(function () {
    return outnum("2");
  })
  .then(function () {
    return outnum("3");
  })
  .then(function () {
    console.log("0");
  });

// 输出1 ,2 ,3 ,0
Promise 对象中的方法
Promise.all 方法

当首次加载某个页面时,由于数据庞大需要分别同时发送多个异步请求向服务器获取数据,最终所有数据返回之后做下一步操作(如“隐藏页面的加载 loading 动画”)。由于很难捕获这些异步请求全部成功的时机,导致这个需求实现起来相当困难。难道就没有解决办法了吗?🤔 这时使用 Promise.all 方法就可以解决这种问题。

// Promise.all 方法中的参数是一个数组,数组中的每个元素是实例化后的 Promise 对象,格式如下代码:

Promise.all([p1,p2,p3,...]).then(res=>{
  // 所有请求成功后的操作步骤
},error=>{
  // 某一个请求失败后的操作步骤
});
  1. 定义一个函数 p1,返回一个 Promise 对象,在返回过程中,执行一个延时操作,定义一个参数 n ,如果参数 n 大于 0 ,则返回该数据,否则,则返回 “ 不能小于 0“ 的字符信息。
  2. 调用 Promise.all 方法,使用不同的参数,调用三次 p1 函数,当全部执行成功或有一个执行失败后,分别查看控制台的输出信息。
function p1(n) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      if (n > 0) {
        resolve(n);
      } else {
        reject("不能小于0");
      }
    }, 1000);
  });
}
// 输出5,6,7
Promise.all([p1(5), p1(6), p1(7)]).then(
  function (v) {
    console.log(v);
  },
  function (e) {
    console.log(e);
  }
);
//输出不能小于0
Promise.all([p1(5), p1(-2), p1(7)]).then(
  function (v) {
    console.log(v);
  },
  function (e) {
    console.log(e);
  }
);
Promise.race 方法

Promise.all 方法不同,Promise.race 方法是多个 Promise 实例化对象在比赛, 执行最快的那个任务的结果,将返回给 then 方法中的对应回调函数中,通过这种方式,可以检测页面中某个请求是否超时,并输出相关的提示信息。

Promise.race([p1,p2,p3,...]).then(
    function(v){
      //获取最快任务成功时的返回值
  },
  function(){
      //获取最快任务失败时的返回值
  }
)
async 关键字

async 英文单词的意思是异步,虽然它是 ES7 中新增加的一个关键字,但它的本质是一种语法糖写法(语法糖是一种简化后的代码写化,它能方便程序员的代码开发),async 通常写在一个函数的前面,表示这是一个异步请求的函数,将返回一个 Promise 对象,并可以通过 then 方法取到函数中的返回值,下面通过一个简单示例来说明它的使用。

await 关键字

await 可以理解为 async wait 的简写,表示等待异步执行完成,await 必须在 async 定义的函数中,不能单独使用,await 后可以返回任意的表达式,如果是正常内容,则直接执行,如果是异步请求,必须等待请求完成后,才会执行下面的代码,来看下列代码。

// 函数 p 返回的是一个 Promise 对象,在对象中,延时 2 秒,执行成功回调函数,相当于模拟一次异步请求
function p(v) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      // 在 p 函数执行时,将函数的实参值 v ,作为执行成功回调函数的返回值。
      resolve(v);
    }, 2000);
  });
}

// 一个用于正常输出内容的函数
function log() {
  console.log("2.正在操作");
}

async function fn() {
  console.log("1.开始");
  await log();
  let p1 = await p("3.异步请求");
  console.log(p1);
  console.log("4.结束");
}
fn();
多层嵌套传参数的优化

需要发送三次异步请求,第一次请求,成功后获取返回 1,并将该值作为参数并加 2,发送第二次请求,成功后获取返回值,并将该值作为参数并加 3,发送第三次请求,成功后输出全部的返回值,如果三次请求都成功了,则在控制台输出 “登录成功!”的字样。

// 函数 p 返回的是一个 Promise 对象,在对象中,延时 2 秒,执行成功回调函数,相当于模拟一次异步请求
function p(v) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      // 在 p 函数执行时,将函数的实参值 v ,作为执行成功回调函数的返回值。
      resolve(v);
    }, 2000);
  });
}
async function fn() {
  let p1 = await p("1");
  let p2 = await p(p1 + "2");
  let p3 = await p(p2 + "3");
  console.log(p3);
  console.log("登录成功!");
}
fn();
多个并列异步请求的调优

await 在处理多个异步请求时,如果请求之间有嵌套关系,可以一次一次按顺序发送请求,但是如果各个请求之间无任何关联,则可以将这些请求借助 Promise.all 一次性并列发送,使用 await 关键字获取请求的结果,并根据返回的结果进行下一步操作。如下列需求。页面首次加载时,将会发送三次无任何关联的异步请求,当这三次请求成功后,在控制台输出“隐藏加载动画!”字样

// 函数 p 返回的是一个 Promise 对象,在对象中,延时 2 秒,执行成功回调函数,相当于模拟一次异步请求
function p(v) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      // 在 p 函数执行时,将函数的实参值 v ,作为执行成功回调函数的返回值。
      resolve(v);
    }, 2000);
  });
}
async function fn() {  //并发方式
  await Promise.all([p("a"), p("b"), p("c")]);
  console.log("隐藏加载动画!");
}
async function fn() { //顺序执行
  await p("a");
  await p("b");
  await p("c");
  console.log("隐藏加载动画!");
}
fn();

模块化

export
import

Proxy

什么是 Proxy

Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后通过对象的代理对象进行操作。也可以理解为在外界与对象之间建立了一道门,外界要访问该对象必须先打开这道门,如果想要获得打开该门的钥匙,就要遵守一个访问“条约”,允许对来访人员进行改造(提供一种机制:可以对外界的访问进行过滤和改写)。

var proxy = new Proxy(target, handler);
  • target:要拦截的目标对象。
  • handler:制定拦截行为的对象。
let target = {};
let proxy = new Proxy(target, {});
proxy.name = "闷墩儿";
console.log(proxy.name);
console.log(target.name);

target.name = "憨憨";
console.log(proxy.name);
console.log(target.name);

在上面的例子中 proxy 的所有操作都转发给了 target 对象,当在 proxy 上创建了 name 属性之后,相应的 target 上也会创建 name 属性。由于 target.nameproxy.name 都是引用的 target.name,所以当修改了 target.name 的值后,proxy.name 的值也会修改。

Proxy 的实例方法
拦截方法方法说明
get(target, propKey, receiver)拦截对象属性的读取。
set(target, propKey, value, receiver)拦截对象属性的设置。
has(target, propKey)拦截 propKey in proxy 的操作。
deleteProperty(target, propKey)拦截 delete proxy[propKey]的操作。
ownKeys(target)拦截 Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for…in 循环,返回一个数组。
getOwnPropertyDescriptor(target, propKey)拦截 Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
defineProperty(target, propKey, propDesc)拦截 Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
preventExtensions(target)拦截 Object.preventExtensions(proxy),返回一个布尔值。
getPrototypeOf(target)拦截 Object.getPrototypeOf(proxy),返回一个对象。
isExtensible(target)拦截 Object.isExtensible(proxy),返回一个布尔值。
setPrototypeOf(target, proto)拦截 Object.setPrototypeOf(proxy, proto),返回一个布尔值。
apply(target, object, args)拦截 Proxy 实例作为函数调用的操作。
construct(target, args)拦截 Proxy 实例作为构造函数调用的操作。
get(target, propKey, receiver)
  • target:被读取属性的目标对象。
  • propKey:要读取的属性键值。
  • receiver:操作发生的对象。
let dog = {
  name: "闷墩儿",
};
var proxy = new Proxy(dog, {
  get(target, propKey) {
    // 遍历目标对象的属性键值
    if (propKey in target) {
      return target[propKey]; // 返回相应的属性值
    } else {
      throw new ReferenceError(propKey + " 属性不存在");
    }
  },
});
console.log("访问 dog 对象中的 name 属性值为:" + proxy.name);
console.log("访问不存在的 age 属性:" + proxy.age);
set(target, propKey, value, receiver)
  • target:用于接收属性的目标对象。
  • propKey:要写入的属性键值。
  • value:要写入的属性值。
  • receiver:操作发生的对象。
let validator = {
  set(target, propKey, value) {
    if (propKey === "age") {
      // 判断 age 属性值是否时数字
      if (!Number.isInteger(value)) {
        throw new TypeError("狗狗的年龄只能是整型哦!");
      }
    }
    target[prop] = value;
    return true;
  },
};

let dog = new Proxy({}, validator);
console.log((dog.age = "22"));
has(target, propKey)
  • target:读取属性的目标对象。
  • propKey:要检查的属性键值。
let dog = {
  name: "闷墩儿",
  age: 2,
};
let handler = {
  has(target, propKey) {
    if (propKey == "age" && target[propKey] < 5) {
      console.log(`${target.name}的年龄小于 5 岁哦!`);
      return true;
    }
  },
};
let proxy = new Proxy(dog, handler);

console.log("age" in proxy);
ownKeys(target)

ownKeys 方法用于拦截对象自身属性的读取操作,具体可以拦截以下四种操作:

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()
  • for…in
let dog = {
  name: "闷墩儿",
  age: 2,
  food: "狗罐头",
};
const proxy = new Proxy(dog, {
  ownKeys() {
    return ["name", "color"];
  },
});

for (let key in proxy) {
  console.log(key); // 输出 name
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值