目錄
const 與let 變數
展开运算符
剩余参数(可变参数)
ES6箭头函数
javascript标准函数this
箭头函数和this
默认参数函数
默认值与解构
Javascript类
super 和 extends
字符串模板
iterator, generator
模块
Map,Set 和 WeakMap,WeakSet
Proxies
Symbols
Math,Number,String,Object 的新API
Promises
首頁 web前端 js教程 es6有哪些新特性

es6有哪些新特性

Mar 02, 2021 am 11:21 AM
es6

es6新特性:const與let變數、模板字面量、解構、增強的物件字面量、for...of迴圈、展開運算子(...)、剩餘參數(可變參數) 、ES6箭頭函數、類別的支援、字串模板、iterator、generator、模組、Symbols等。

es6有哪些新特性

本教學操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。

const 與let 變數

使用var#帶來的麻煩:

function getClothing(isCold) {
  if (isCold) {
    var freezing = 'Grab a jacket!';
  } else {
    var hot = 'It's a shorts kind of day.';
    console.log(freezing);
  }
}
登入後複製

執行getClothing(false) 後面輸出的是undefined,這是因為執行function函數之前,所有變數都會被提升, 提升到函數作用域頂端.

letconst聲明的變數解決了這種問題,因為他們是區塊級作用域, 在程式碼區塊(用 {}表示)中使用letconst宣告變數, 此變數會陷入暫時性死區直到該變數的宣告被處理。

function getClothing(isCold) {
  if (isCold) {
    const freezing = 'Grab a jacket!';
  } else {
    const hot = 'It's a shorts kind of day.';
    console.log(freezing);
  }
}
登入後複製

運行getClothing(false)後輸出的是ReferenceError: freezing is not defined,因為freezing 沒有在else 語句、函數作用域或全域作用域內聲明,所以拋出ReferenceError

關於使用letconst規則:

  • #使用let聲明的變數可以重新賦值,但是無法在同一作用域內重新宣告
  • 使用const宣告的變數必須賦值初始化,但是不能在相同作用域類別重新宣告也無法重新賦值.

es6有哪些新特性
es6有哪些新特性

【相關推薦:JavaScript影片教學

##範本字面上

# #在ES6之前,將字串連接到一起的方法是 concat()

方法,如

const student = {
  name: 'Richard Kalehoff',
  guardian: 'Mr. Kalehoff'
};
const teacher = {
  name: 'Mrs. Wilson',
  room: 'N231'
}
let message = student.name + ' please see ' + teacher.name + ' in ' + teacher.room + ' to pick up your report card.';
登入後複製

模板字面量本質上是包含嵌入式表達式的字串字面量. 模板字面量用倒引號( `` )(而不是單引號( '' ) 或雙引號( "" ))表示,可以包含以${expression} 表示的佔位符

let message = `${student.name} please see ${teacher.name} in ${teacher.room} to pick up your report card.`;
登入後複製
解構

在ES6,可以使用解構

從陣列和物件提取值並賦值給獨特的變數

解構數組的值:
const point = [10, 25, -34];
const [x, y, z] = point;
console.log(x, y, z);
登入後複製

Prints: 10 25 -34

[]表示被解構的陣列, x,y,z表示要將陣列中的值儲存在其中的變數, 在解構數組是, 還可以忽略值, 例如const[x,,z]=point,忽略y

座標.

解構對象中的值:

const gemstone = {
  type: 'quartz',
  color: 'rose',
  karat: 21.29
};
const {type, color, karat} = gemstone;
console.log(type, color, karat);
登入後複製
花括號{ } 表示被解構的對象,typecolorkarat表示要將物件中的屬性儲存到其中的變數

物件字面量簡寫法

let type = 'quartz';
let color = 'rose';
let carat = 21.29;
const gemstone = {
  type: type,
  color: color,
  carat: carat
};
console.log(gemstone);
登入後複製
使用和所指派的變數名稱相同的名稱初始化物件時如果屬性名稱和所指派的變數名稱一樣,那麼就可以從物件屬性中刪除這些重複的變數名稱。

let type = 'quartz';
let color = 'rose';
let carat = 21.29;
const gemstone = {type,color,carat};
console.log(gemstone);
登入後複製
簡寫方法的名稱:

const gemstone = {
  type,
  color,
  carat,
  calculateWorth: function() {
    // 将根据类型(type),颜色(color)和克拉(carat)计算宝石(gemstone)的价值
  }
};
登入後複製
匿名函數被指派給屬性 calculateWorth,但真的需要 function 關鍵字嗎?在 ES6 中不需要!

let gemstone = {
  type,
  color,
  carat,
  calculateWorth() { ... }
};
登入後複製
for...of迴圈

for...of
迴圈是最新加入 JavaScript 迴圈系列中的迴圈。 它結合了其兄弟循環形式for 循環和for...in 循環的優勢,可以循環任何可迭代(也就是遵守可迭代協議)類型的數據。預設情況下,包含以下資料類型:StringArrayMapSet,注意不包含Object 資料型態(即{})。 預設情況下,物件不可迭代

for迴圈

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (let i = 0; i <code></code>for<br> 迴圈的最大缺點是需要追蹤計數器和退出條件。 <code> 雖然 </code>for 循環在循環數組時的確具有優勢,但是某些資料結構不是數組,因此並非始終適合使用 loop 循環。 <p></p>for...in循環<p></p><pre class="brush:php;toolbar:false">const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (const index in digits) {
  console.log(digits[index]);
}
登入後複製
仍然需要使用index 來存取陣列的值

當你需要在陣列中加入額外的方法(或另一個物件)時,for...in 迴圈會帶來很大的麻煩。因為for...in 循環循環存取所有可枚舉的屬性,表示如果向數組的原型中添加任何其他屬性

,這些屬性也會出現在循環中。 ###
Array.prototype.decimalfy = function() {
  for (let i = 0; i <blockquote><p>forEach 循环 是另一种形式的 JavaScript 循环。但是,forEach() 实际上是数组方法,因此只能用在数组中。也无法停止或退出 forEach 循环。如果希望你的循环中出现这种行为,则需要使用基本的 for 循环。</p></blockquote><p>for...of循环<br><code>for...of</code> 循环用于循环访问任何可迭代的数据类型。<br><code>for...of</code> 循环的编写方式和 <code>for...in</code> 循环的基本一样,只是将 <code>in</code> 替换为 <code>of</code>,可以忽略索引。</p><pre class="brush:php;toolbar:false">const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (const digit of digits) {
  console.log(digit);
}
登入後複製

建议使用复数对象名称来表示多个值的集合。这样,循环该集合时,可以使用名称的单数版本来表示集合中的单个值。例如,for (const button of buttons) {…}

for...of 循环还具有其他优势,解决了 for 和 for...in 循环的不足之处。你可以随时停止或退出 for...of 循环。

for (const digit of digits) {
  if (digit % 2 === 0) {
    continue;
  }
  console.log(digit);
}
登入後複製

不用担心向对象中添加新的属性。for...of 循环将只循环访问对象中的值。

Array.prototype.decimalfy = function() {
  for (i = 0; i <h3 id="strong-展开运算符-strong"><strong>展开运算符</strong></h3><p><strong>展开运算符</strong>(用三个连续的点 (<code>...</code>) 表示)是 ES6 中的新概念,使你能够将字面量对象展开为多个元素</p><pre class="brush:php;toolbar:false">const books = ["Don Quixote", "The Hobbit", "Alice in Wonderland", "Tale of Two Cities"];
console.log(...books);
登入後複製

Prints: Don Quixote The Hobbit Alice in Wonderland Tale of Two Cities

展开运算符的一个用途是结合数组。

如果你需要结合多个数组,在有展开运算符之前,必须使用 Arrayconcat() 方法。

const fruits = ["apples", "bananas", "pears"];
const vegetables = ["corn", "potatoes", "carrots"];
const produce = fruits.concat(vegetables);
console.log(produce);
登入後複製

Prints: ["apples", "bananas", "pears", "corn", "potatoes", "carrots"]

使用展开符来结合数组

const fruits = ["apples", "bananas", "pears"];
const vegetables = ["corn", "potatoes", "carrots"];
const produce = [...fruits,...vegetables];
console.log(produce);
登入後複製

剩余参数(可变参数)

使用展开运算符将数组展开为多个元素, 使用剩余参数可以将多个元素绑定到一个数组中.
剩余参数也用三个连续的点 ( ... ) 表示,使你能够将不定数量的元素表示为数组.

用途1: 将变量赋数组值时:

const order = [20.17, 18.67, 1.50, "cheese", "eggs", "milk", "bread"];
const [total, subtotal, tax, ...items] = order;
console.log(total, subtotal, tax, items);
登入後複製

用途2: 可变参数函数
对于参数不固定的函数,ES6之前是使用参数对象(arguments)处理:

function sum() {
  let total = 0;  
  for(const argument of arguments) {
    total += argument;
  }
  return total;
}
登入後複製

在ES6中使用剩余参数运算符则更为简洁,可读性提高:

function sum(...nums) {
  let total = 0;  
  for(const num of nums) {
    total += num;
  }
  return total;
}
登入後複製

ES6箭头函数

ES6之前,使用普通函数把其中每个名字转换为大写形式:

const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(function(name) { 
  return name.toUpperCase();
});
登入後複製

箭头函数表示:

const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(
  name => name.toUpperCase()
);
登入後複製
登入後複製

普通函数可以是函数声明或者函数表达式, 但是箭头函数始终都是表达式, 全程是箭头函数表达式, 因此因此仅在表达式有效时才能使用,包括:

  • 存储在变量中,
  • 当做参数传递给函数,
  • 存储在对象的属性中。
const greet = name => `Hello ${name}!`;
登入後複製

可以如下调用:

greet('Asser');
登入後複製

如果函数的参数只有一个,不需要使用()包起来,但是只有一个或者多个, 则必须需要将参数列表放在圆括号内:

// 空参数列表需要括号
const sayHi = () => console.log('Hello Udacity Student!');
// 多个参数需要括号
const orderIceCream = (flavor, cone) => console.log(`Here's your ${flavor} ice cream in a ${cone} cone.`);
orderIceCream('chocolate', 'waffle');
登入後複製

一般箭头函数都只有一个表达式作为函数主题:

const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(
  name => name.toUpperCase()
);
登入後複製
登入後複製

这种函数表达式形式称为简写主体语法:

  • 在函数主体周围没有花括号,
  • 自动返回表达式

但是如果箭头函数的主体内需要多行代码, 则需要使用常规主体语法:

  • 它将函数主体放在花括号内
  • 需要使用 return 语句来返回内容。
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map( name => {
  name = name.toUpperCase();
  return `${name} has ${name.length} characters in their name`;
});
登入後複製

javascript标准函数this

1、new 对象

const mySundae = new Sundae('Chocolate', ['Sprinkles', 'Hot Fudge']);
登入後複製

sundae这个构造函数内的this的值是实例对象, 因为他使用new被调用.

2、指定的对象

const result = obj1.printName.call(obj2);
登入後複製

函数使用call/apply被调用,this的值指向指定的obj2,因为call()第一个参数明确设置this的指向

3、上下`文对象

data.teleport();
登入後複製

函数是对象的方法, this指向就是那个对象,此处this就是指向data.

4、全局对象或 undefined

teleport();
登入後複製

此处是this指向全局对象,在严格模式下,指向undefined.

javascript中this是很复杂的概念, 要详细判断this,请参考this豁然开朗

箭头函数和this

对于普通函数, this的值基于函数如何被调用, 对于箭头函数,this的值基于函数周围的上下文, 换句话说,this的值和函数外面的this的值是一样的.

function IceCream() {
    this.scoops = 0;
}
// 为 IceCream 添加 addScoop 方法
IceCream.prototype.addScoop = function() {
    setTimeout(function() {
        this.scoops++;
        console.log('scoop added!');
        console.log(this.scoops); // undefined+1=NaN
        console.log(dessert.scoops); //0
    }, 500);
};
登入後複製

标题

const dessert = new IceCream();
dessert.addScoop();

传递给 setTimeout() 的函数被调用时没用到 newcall()apply(),也没用到上下文对象。意味着函数内的 this 的值是全局对象,不是 dessert 对象。实际上发生的情况是,创建了新的 scoops 变量(默认值为 undefined),然后递增(undefined + 1 结果为 NaN);

解决此问题的方式之一是使用闭包(closure):

// 构造函数
function IceCream() {
  this.scoops = 0;
}
// 为 IceCream 添加 addScoop 方法
IceCream.prototype.addScoop = function() {
  const cone = this; // 设置 `this` 给 `cone`变量
  setTimeout(function() {
    cone.scoops++; // 引用`cone`变量
    console.log('scoop added!'); 
    console.log(dessert.scoops);//1
  }, 0.5);
};
const dessert = new IceCream();
dessert.addScoop();
登入後複製

箭头函数的作用正是如此, 将setTimeOut()的函数改为剪头函数:

// 构造函数
function IceCream() {
  this.scoops = 0;
}
// 为 IceCream 添加 addScoop 方法
IceCream.prototype.addScoop = function() {
  setTimeout(() => { // 一个箭头函数被传递给setTimeout
    this.scoops++;
    console.log('scoop added!');
    console.log(dessert.scoops);//1
  }, 0.5);
};
const dessert = new IceCream();
dessert.addScoop();
登入後複製

默认参数函数

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';
  return `${greeting} ${name}!`;
}
greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!
登入後複製

greet() 函数中混乱的前两行的作用是什么?它们的作用是当所需的参数未提供时,为函数提供默认的值。但是看起来很麻烦, ES6引入一种新的方式创建默认值, 他叫默认函数参数:

function greet(name = 'Student', greeting = 'Welcome') {
  return `${greeting} ${name}!`;
}
greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!
登入後複製

默认值与解构

1、默认值与解构数组

function createGrid([width = 5, height = 5]) {
  return `Generates a ${width} x ${height} grid`;
}
登入後複製

createGrid([]); // Generates a 5 x 5 grid
createGrid([2]); // Generates a 2 x 5 grid
createGrid([2, 3]); // Generates a 2 x 3 grid
createGrid([undefined, 3]); // Generates a 5 x 3 grid

createGrid() 函数预期传入的是数组。它通过解构将数组中的第一项设为 width,第二项设为 height。如果数组为空,或者只有一项,那么就会使用默认参数,并将缺失的参数设为默认值 5。

但是存在一个问题:

createGrid(); // throws an error
登入後複製

Uncaught TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined

出现错误,因为 createGrid() 预期传入的是数组,然后对其进行解构。因为函数被调用时没有传入数组,所以出现问题。但是,我们可以使用默认的函数参数!

function createGrid([width = 5, height = 5] = []) {
  return `Generating a grid of ${width} by ${height}`;
}
createGrid(); // Generates a 5 x 5 grid
登入後複製

Returns: Generates a 5 x 5 grid

2、默认值与解构函数

就像使用数组默认值解构数组一样,函数可以让对象成为一个默认参数,并使用对象解构:

function createSundae({scoops = 1, toppings = ['Hot Fudge']}={}) {
  const scoopText = scoops === 1 ? 'scoop' : 'scoops';
  return `Your sundae has ${scoops} ${scoopText} with ${toppings.join(' and ')} toppings.`;
}
createSundae({}); // Your sundae has 1 scoop with Hot Fudge toppings.
createSundae({scoops: 2}); // Your sundae has 2 scoops with Hot Fudge toppings.
createSundae({scoops: 2, toppings: ['Sprinkles']}); // Your sundae has 2 scoops with Sprinkles toppings.
createSundae({toppings: ['Cookie Dough']}); // Your sundae has 1 scoop with Cookie Dough toppings.
createSundae(); // Your sundae has 1 scoop with Hot Fudge toppings.
登入後複製

3、数组默认值与对象默认值

默认函数参数只是个简单的添加内容,但是却带来很多便利!与数组默认值相比,对象默认值具备的一个优势是能够处理跳过的选项。看看下面的代码:

function createSundae({scoops = 1, toppings = ['Hot Fudge']} = {}) { … }
登入後複製

createSundae() 函数使用对象默认值进行解构时,如果你想使用 scoops 的默认值,但是更改 toppings,那么只需使用 toppings 传入一个对象:

createSundae({toppings: ['Hot Fudge', 'Sprinkles', 'Caramel']});
登入後複製

将上述示例与使用数组默认值进行解构的同一函数相对比。

function createSundae([scoops = 1, toppings = ['Hot Fudge']] = []) { … }
登入後複製

对于这个函数,如果想使用 scoops 的默认数量,但是更改 toppings,则必须以这种奇怪的方式调用你的函数:

createSundae([undefined, ['Hot Fudge', 'Sprinkles', 'Caramel']]);
登入後複製

因为数组是基于位置的,我们需要传入 undefined 以跳过第一个参数(并使用默认值)来到达第二个参数。

Javascript类

ES5创建类:

function Plane(numEngines) {
  this.numEngines = numEngines;
  this.enginesActive = false;
}
// 由所有实例 "继承" 的方法
Plane.prototype.startEngines = function () {
  console.log('starting engines...');
  this.enginesActive = true;
};
登入後複製

ES6类只是一个语法糖,原型继续实际上在底层隐藏起来, 与传统类机制语言有些区别.

class Plane {
  //constructor方法虽然在类中,但不是原型上的方法,只是用来生成实例的.
  constructor(numEngines) {
    this.numEngines = numEngines;
    this.enginesActive = false;
  }
  //原型上的方法, 由所有实例对象共享.
  startEngines() {
    console.log('starting engines…');
    this.enginesActive = true;
  }
}
console.log(typeof Plane); //function
登入後複製

javascript中类其实只是function, 方法之间不能使用,,不用逗号区分属性和方法.

静态方法

要添加静态方法,请在方法名称前面加上关键字 static

class Plane {
  constructor(numEngines) {
    this.numEngines = numEngines;
    this.enginesActive = false;
  }
  static badWeather(planes) {
    for (plane of planes) {
      plane.enginesActive = false;
    }
  }
  startEngines() {
    console.log('starting engines…');
    this.enginesActive = true;
  }
}
登入後複製
  • 关键字class带来其他基于类的语言的很多思想,但是没有向javascript中添加此功能
  • javascript类实际上还是原型继承
  • 创建javascript类的新实例时必须使用new关键字

super 和 extends

使用新的super和extends关键字扩展类:

class Tree {
  constructor(size = '10', leaves = {spring: 'green', summer: 'green', fall: 'orange', winter: null}) {
    this.size = size;
    this.leaves = leaves;
    this.leafColor = null;
  }
  changeSeason(season) {
    this.leafColor = this.leaves[season];
    if (season === 'spring') {
      this.size += 1;
    }
  }
}
class Maple extends Tree {
  constructor(syrupQty = 15, size, leaves) {
    super(size, leaves); //super用作函数
    this.syrupQty = syrupQty;
  }
  changeSeason(season) {
    super.changeSeason(season);//super用作对象
    if (season === 'spring') {
      this.syrupQty += 1;
    }
  }
  gatherSyrup() {
    this.syrupQty -= 3;
  }
}
登入後複製

使用ES5编写同样功能的类:

function Tree(size, leaves) {
  this.size = size || 10;
  this.leaves = leaves || {spring: 'green', summer: 'green', fall: 'orange', winter: null};
  this.leafColor;
}
Tree.prototype.changeSeason = function(season) {
  this.leafColor = this.leaves[season];
  if (season === 'spring') {
    this.size += 1;
  }
}
function Maple (syrupQty, size, leaves) {
  Tree.call(this, size, leaves);
  this.syrupQty = syrupQty || 15;
}
Maple.prototype = Object.create(Tree.prototype);
Maple.prototype.constructor = Maple;
Maple.prototype.changeSeason = function(season) {
  Tree.prototype.changeSeason.call(this, season);
  if (season === 'spring') {
    this.syrupQty += 1;
  }
}
Maple.prototype.gatherSyrup = function() {
  this.syrupQty -= 3;
}
登入後複製

super 必须在 this 之前被调用

在子类构造函数中,在使用 this 之前,必须先调用超级类。

class Apple {}
class GrannySmith extends Apple {
  constructor(tartnessLevel, energy) {
    this.tartnessLevel = tartnessLevel; // 在 'super' 之前会抛出一个错误!
    super(energy); 
  }
}
登入後複製

字符串模板

字符串模板相对简单易懂些。ES6中允许使用反引号 ` 来创建字符串,此种方法创建的字符串里面可以包含由美元符号加花括号包裹的变量${vraible}。如果你使用过像C#等后端强类型语言的话,对此功能应该不会陌生。

//产生一个随机数
var num=Math.random();
//将这个数字输出到console
console.log(`your num is ${num}`);
登入後複製

iterator, generator

这一部分的内容有点生涩,详情可以参见这里。以下是些基本概念。

  • iterator:它是这么一个对象,拥有一个next方法,这个方法返回一个对象{done,value},这个对象包含两个属性,一个布尔类型的done和包含任意值的value
  • iterable: 这是这么一个对象,拥有一个obj[@@iterator]方法,这个方法返回一个iterator
  • generator: 它是一种特殊的iterator。反的next方法可以接收一个参数并且返回值取决与它的构造函数(generator function)。generator同时拥有一个throw方法
  • generator 函数: 即generator的构造函数。此函数内可以使用yield关键字。在yield出现的地方可以通过generator的nextthrow方法向外界传递值。generator 函数是通过function*来声明的
  • yield 关键字:它可以暂停函数的执行,随后可以再进进入函数继续执行

模块

在ES6标准中,JavaScript原生支持module了。这种将JS代码分割成不同功能的小块进行模块化的概念是在一些三方规范中流行起来的,比如CommonJS和AMD模式。

将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用。下面的例子来自tutsplus:

// point.js
module "point" {
    export class Point {
        constructor (x, y) {
            public x = x;
            public y = y;
        }
    }
}
 
// myapp.js
//声明引用的模块
module point from "/point.js";
//这里可以看出,尽管声明了引用的模块,还是可以通过指定需要的部分进行导入
import Point from "point";
 
var origin = new Point(0, 0);
console.log(origin);
登入後複製

Map,Set 和 WeakMap,WeakSet

这些是新加的集合类型,提供了更加方便的获取属性值的方法,不用像以前一样用hasOwnProperty来检查某个属性是属于原型链上的呢还是当前对象的。同时,在进行属性值添加与获取时有专门的getset 方法。

下方代码来自es6feature

// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;

// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;
登入後複製

有时候我们会把对象作为一个对象的键用来存放属性值,普通集合类型比如简单对象会阻止垃圾回收器对这些作为属性键存在的对象的回收,有造成内存泄漏的危险。而WeakMap,WeakSet则更加安全些,这些作为属性键的对象如果没有别的变量在引用它们,则会被回收释放掉,具体还看下面的例子。

正文代码来自es6feature

// Weak Maps
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size === undefined

// Weak Sets
var ws = new WeakSet();
ws.add({ data: 42 });//因为添加到ws的这个临时对象没有其他变量引用它,所以ws不会保存它的值,也就是说这次添加其实没有意思
登入後複製

Proxies

Proxy可以监听对象身上发生了什么事情,并在这些事情发生后执行一些相应的操作。一下子让我们对一个对象有了很强的追踪能力,同时在数据绑定方面也很有用处。

以下例子借用自这里。

//定义被侦听的目标对象
var engineer = { name: 'Joe Sixpack', salary: 50 };
//定义处理程序
var interceptor = {
  set: function (receiver, property, value) {
    console.log(property, 'is changed to', value);
    receiver[property] = value;
  }
};
//创建代理以进行侦听
engineer = Proxy(engineer, interceptor);
//做一些改动来触发代理
engineer.salary = 60;//控制台输出:salary is changed to 60
登入後複製

上面代码我已加了注释,这里进一步解释。对于处理程序,是在被侦听的对象身上发生了相应事件之后,处理程序里面的方法就会被调用,上面例子中我们设置了set的处理函数,表明,如果我们侦听的对象的属性被更改,也就是被set了,那这个处理程序就会被调用,同时通过参数能够得知是哪个属性被更改,更改为了什么值。

Symbols

我们知道对象其实是键值对的集合,而键通常来说是字符串。而现在除了字符串外,我们还可以用symbol这种值来做为对象的键。Symbol是一种基本类型,像数字,字符串还有布尔一样,它不是一个对象。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的。之后就可以用这个返回值做为对象的键了。Symbol还可以用来创建私有属性,外部无法直接访问由symbol做为键的属性值。

以下例子来自es6features

(function() {

  // 创建symbol
  var key = Symbol("key");

  function MyClass(privateData) {
    this[key] = privateData;
  }

  MyClass.prototype = {
    doStuff: function() {
      ... this[key] ...
    }
  };

})();

var c = new MyClass("hello")
c["key"] === undefined//无法访问该属性,因为是私有的
登入後複製

Math,Number,String,Object 的新API

对Math,Number,String还有Object等添加了许多新的API。下面代码同样来自es6features,对这些新API进行了简单展示。

Number.EPSILON
Number.isInteger(Infinity) // false
Number.isNaN("NaN") // false

Math.acosh(3) // 1.762747174039086
Math.hypot(3, 4) // 5
Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2

"abcde".contains("cd") // true
"abc".repeat(3) // "abcabcabc"

Array.from(document.querySelectorAll('*')) // Returns a real Array
Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
[0, 0, 0].fill(7, 1) // [0,7,7]
[1,2,3].findIndex(x => x == 2) // 1
["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
["a", "b", "c"].keys() // iterator 0, 1, 2
["a", "b", "c"].values() // iterator "a", "b", "c"

Object.assign(Point, { origin: new Point(0,0) })
登入後複製

Promises

Promises是处理异步操作的一种模式,之前在很多三方库中有实现,比如jQuery的deferred 对象。当你发起一个异步请求,并绑定了.when(), .done()等事件处理程序时,其实就是在应用promise模式。

//创建promise
var promise = new Promise(function(resolve, reject) {
    // 进行一些异步或耗时操作
    if ( /*如果成功 */ ) {
        resolve("Stuff worked!");
    } else {
        reject(Error("It broke"));
    }
});
//绑定处理程序
promise.then(function(result) {
	//promise成功的话会执行这里
    console.log(result); // "Stuff worked!"
}, function(err) {
	//promise失败会执行这里
    console.log(err); // Error: "It broke"
});
登入後複製

更多编程相关知识,请访问:编程视频!!

以上是es6有哪些新特性的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

ES6怎麼求數組反轉 ES6怎麼求數組反轉 Oct 26, 2022 pm 06:19 PM

在ES6中,可以利用數組物件的reverse()方法來實現數組反轉,該方法用於顛倒數組中元素的順序,將最後一個元素放在第一位,而第一個元素放在最後,語法「array.reverse()」。 reverse()方法會修改原始數組,如果不想修改需要配合擴充運算子「...」使用,語法「[...array].reverse()」。

async是es6還是es7的 async是es6還是es7的 Jan 29, 2023 pm 05:36 PM

async是es7的。 async和await是ES7中新增內容,是對於非同步操作的解決方案;async/await可以說是co模組和生成器函數的語法糖,用更清晰的語意解決js非同步程式碼。 async顧名思義是「非同步」的意思,async用於聲明一個函數是異步的;async和await有一個嚴格規定,兩者都離不開對方,且await只能寫在async函數中。

es6怎麼找出2個數組中不同項 es6怎麼找出2個數組中不同項 Nov 01, 2022 pm 06:07 PM

步驟:1、將兩個陣列分別轉換為set類型,語法「newA=new Set(a);newB=new Set(b);」;2、利用has()和filter()求差集,語法“ new Set([...newA].filter(x =>!newB.has(x)))”,差集元素會被包含在一個set集合中返回;3、利用Array.from將集合轉為數組類型,語法“Array.from(集合)”。

小程式為什麼要將es6轉es5 小程式為什麼要將es6轉es5 Nov 21, 2022 pm 06:15 PM

為了瀏覽器相容。 ES6作為JS的新規範,加入了許多新的語法和API,但現代瀏覽器對ES6新特性支援不高,所以需將ES6程式碼轉換為ES5程式碼。在微信web開發者工具中,會預設使用babel將開發者ES6語法程式碼轉換為三端都能很好支援的ES5的程式碼,幫助開發者解決環境不同所帶來的開發問題;只需要在專案中配置勾選好「ES6轉ES5」選項即可。

es5和es6怎麼實現陣列去重 es5和es6怎麼實現陣列去重 Jan 16, 2023 pm 05:09 PM

es5中可以利用for語句和indexOf()函數來實現數組去重,語法“for(i=0;i<數組長度;i++){a=newArr.indexOf(arr[i]);if(a== -1){...}}」。在es6中可以利用擴充運算子、Array.from()和Set來去重;需要先將陣列轉為Set物件來去重,然後利用擴充運算子或Array.from()函數來將Set物件轉回數組即可。

es6暫時性死區是什麼意思 es6暫時性死區是什麼意思 Jan 03, 2023 pm 03:56 PM

在es6中,暫時性死區是語法錯誤,是指let和const命令使區塊形成封閉的作用域。在程式碼區塊內,使用let/const指令宣告變數之前,變數都是不可用的,在變數宣告之前屬於該變數的「死區」;這在語法上,稱為「暫時性死區」。 ES6規定暫時性死區和let、const語句不出現變量提升,主要是為了減少運行時錯誤,防止在變量聲明前就使用這個變量,從而導致意料之外的行為。

require是es6語法嗎 require是es6語法嗎 Oct 21, 2022 pm 04:09 PM

不是,require是CommonJS規範的模組化語法;而es6規範的模組化語法是import。 require是運行時加載,import是編譯時加載;require可以寫在程式碼的任意位置,import只能寫在文件的最頂端且不可在條件語句或函數作用域中使用;require運行時才引入模組的屬性所以效能相對較低,import編譯時引入模組的屬性所所以效能稍高。

es6 map有序嗎 es6 map有序嗎 Nov 03, 2022 pm 07:05 PM

map是有序的。 ES6中的map類型是一種儲存著許多鍵值對的有序列表,其中的鍵名和對應的值支持所有數據類型;鍵名的等價性判斷是通過調用“Objext.is()”方法來實現的,所以數字5與字串「5」會被判定為兩種類型,可以分別作為兩種獨立的鍵出現在程式中。

See all articles