Javascript 1.5/1.6 新特性

一、const 常量

  • 声明创建了一个常量并要求有初始值
  • 这个常量不能重写,也不能重新声明,它所在的作用域内不能声明与其名称相同的其他变量或函数
  • 这个常量拥有块作用域

二、let 变量

  • let允许你声明一个作用域被限制在块级中的变量、语句或者表达式。

let绑定不受变量提升的约束,这意味着 let 声明不会被提升到当前执行上下文的顶部。

function do_something() {
  console.log(bar); // undefined
  console.log(foo); // ReferenceError: foo is not defined
  var bar = 1;
  let foo = 2;
}

三、解构赋值

  • 是一个Javascript表达式,这使得可以将值从数组属性从对象提取到不同的变量中。

数组——基本变量赋值

var foo = ["one", "two", "three"];
var [one, two, three] = foo;

数组——声明赋值分离

var a, b;
[a, b] = [1, 2];

数组——默认值

var a, b;
[a=5, b=7] = [1];

数组——交换变量

var a = 1;
var b = 3;
[a, b] = [b, a];

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

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

var a, b; 
[a, b] = f(); 

数组——忽略某些返回值

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

var [a, , b] = f();

数组——将剩余数组赋值给一个变量

var [a, ...b] = [1, 2, 3];

数组——用正则表达式匹配提取值

var url = "https://developer.mozilla.org/en-US/Web/JavaScript";

var parsedURL = /^(w+)://([^/]+)/(.*)$/.exec(url);
console.log(parsedURL); // ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript", index: 0, input: "https://developer.mozilla.org/en-US/Web/JavaScript"]

var [, protocol, fullhost, fullpath] = parsedURL;

对象——简单示例

var o = {p: 42, q: true};
var {p, q} = o;

或是用新变量赋值

var {p: foo, q: bar} = o

对象——无声明赋值

var a, b;
({a, b} = {a: 1, b: 2});//相当于var {a, b} = {a: 1, b: 2}

对象——默认值

var {a = 10, b = 5} = {a: 3};

对象——函数参数默认值(火狐测试失败)

function drawES6Chart({size = 'big', cords = { x: 0, y: 0 }, radius = 25} = {}) 
{
  console.log(size, cords, radius);
  // do some chart drawing
}
drawES6Chart({
  cords: { x: 18, y: 30 },
  radius: 30
});

对象——加载模块

const { Loader, main } = require('toolkit/loader');

解构嵌套对象和数组

var metadata = {
    title: "Scratchpad",
    translations: [
       {
        locale: "de",
        localization_tags: [ ],
        last_edit: "2014-04-14T08:43:37",
        url: "/de/docs/Tools/Scratchpad",
        title: "JavaScript-Umgebung"
       }
    ],
    url: "/en-US/docs/Tools/Scratchpad"
};

var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata;

For of 迭代和解构

var people = [
  {
    name: "Mike Smith",
    family: {
      mother: "Jane Smith",
      father: "Harry Smith",
      sister: "Samantha Smith"
    },
    age: 35
  },
  {
    name: "Tom Jones",
    family: {
      mother: "Norah Jones",
      father: "Richard Jones",
      brother: "Howard Jones"
    },
    age: 25
  }
];

for (var {name: n, family: { father: f } } of people) {
  console.log("Name: " + n + ", Father: " + f);
}

从作为参数实参的对象中提取数据

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

function whois({displayName: displayName, fullName: {firstName: name}}){
  console.log(displayName + " is " + name);
}

var user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

console.log("userId: " + userId(user)); // "userId: 42"
whois(user); // "jdoe is John"
View Code

四、class 类表达式

类表达式是用来定义类的一种语法;它的大部分功能,es5都可以做到,新的class写法只是让对象原型的写法更清晰,更像面向对象编程的语法。

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};

等同于

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

创建一个新的类——declaration-form

class Polygon {
  // ..and an (optional) custom class constructor. If one is
  // not supplied, a default constructor is used instead:
  // constructor() { }
  constructor(height, width) {
    this.name = 'Polygon';
    this.height = height;
    this.width = width;
  }

  // Simple class instance methods using short-hand method
  // declaration
  sayName() {
    ChromeSamples.log('Hi, I am a ', this.name + '.');
  }

  sayHistory() {
    ChromeSamples.log('"Polygon" is derived from the Greek polus (many) ' +
      'and gonia (angle).');
  }

  // We will look at static and subclassed methods shortly
}

创建一个新的类——expression-form

const MyPoly = class Poly {
  getPolyName() {
    ChromeSamples.log('Hi. I was created with a Class expression. My name is ' +
      Poly.name);
  }
};

继承一个已存在的类 Extending an existing class

子类没有自己的this对象,而是继承父类的this对象,然后对其加工。super代表了父类构造函数。如果需要在构造函数中使用this,则必须在使用之前调用super

class Square extends Polygon {
  constructor(length) {
    // The reserved 'super' keyword is for making super-constructor
    // calls and allows access to parent methods.
    //
    // Here, it will call the parent class' constructor with lengths
    // provided for the Polygon's width and height
    super(length, length);
    // Note: In derived classes, super() must be called before you
    // can use 'this'. Leaving this out will cause a reference error.
    this.name = 'Square';
  }

  // Getter/setter methods are supported in classes,
  // similar to their ES5 equivalents
  get area() {
    return this.height * this.width;
  }

  set area(value) {
    this.area = value;
  }
}

this指向子组将,相当于

Component.prototype.constructor.call(this,props)。

覆盖父组件的方法 Subclassing methods of a parent class

class Rectangle extends Polygon {
  constructor(height, width) {
    super(height, width);
    this.name = 'Rectangle';
  }
  // Here, sayName() is a subclassed method which
  // overrides their superclass method of the same name.
  sayName() {
    ChromeSamples.log('Sup! My name is ', this.name + '.');
    super.sayHistory();
  }
}

定义一个静态方法 Defining static methods

// Classes support static members which can be accessed without an
// instance being present.
class Triple {
  // Using the 'static' keyword creates a method which is associated
  // with a class, but not with an instance of the class.
  static triple(n) {
    n = n || 1;
    return n * 3;
  }
}
// super.prop in this example is used for accessing super-properties from
// a parent class. This works fine in static methods too:
class BiggerTriple extends Triple {
  static triple(n) {
    return super.triple(n) * super.triple(n);
  }
}

类支持一个静态成员能在不被实例化的状态下调用

Triple.triple();
Triple.triple(6);
BiggerTriple.triple(3);

扩展浏览器的内置对象和DOM

class MyDate extends Date {
  constructor() {
    super();
  }

  getFormattedDate() {
    var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
      'Oct', 'Nov', 'Dec'];
    return this.getDate() + '-' + months[this.getMonth()] + '-' +
      this.getFullYear();
  }
}
class MyAudio extends Audio {
  constructor() {
    super();
    this._lyrics = '';
  }

  get lyrics() {
    return this._lyrics;
  }

  set lyrics(str) {
    this._lyrics = str;
  }
}

var player = new MyAudio();
player.controls = true;
player.lyrics = 'Never gonna give you up';
document.querySelector('body').appendChild(player);
ChromeSamples.log(player.lyrics);

五、数值扩展

Number的扩展

  • Number.isFinite()
  • Number.isNaN()
  • Number.parseInt()
  • Number.parseFloat()
  • Number.isInteger()
  • Number.MAX_SAFE_INTEGER
  • Number.MIN_SAFE_INTEGER

 Math对象扩展

Math.trunc():去除一个数的小数部分,返回整数部分。

Math.trunc(4.1) // 4
Math.trunc(4.9) // 4
Math.trunc(-4.1) // -4
Math.trunc(-4.9) // -4

Math.sign方法用来判断一个数到底是正数、负数、还是零。

Math.sign(-5) // -1
Math.sign(5) // +1
Math.sign(0) // +0
Math.sign(-) // -0
Math.sign(NaN) // NaN

六、数组扩展

Array.prototype.indexOf()

  • indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
  • indexOf使用strict equality进行判断 searchElement与数组中包含的元素之间的关系。

语法:

arr.indexOf(searchvalue,fromindex)

Array.prototype.lastIndexOf()

  • lastIndexOf() 方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始。

语法:

arr.lastIndexOf(searchElement[, fromIndex = arr.length - 1])

Array.prototype.every()

  • every()方法测试数组的所有元素是否都通过了指定函数的测试。返回Boolean类型值。
  • callback被调用时传入三个参数:元素值,元素的索引,原数组。
  • every 遍历的元素范围在第一次调用 callback 之前就已确定了。在调用 every 之后添加到数组中的元素不会被 callback 访问到。

语法:

arr.every(callback[, thisArg])

Array.prototype.filter()

  • filter()方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
  • callback 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。
  • filter 遍历的元素范围在第一次调用 callback 之前就已经确定了。

语法:

var new_array = arr.filter(callback[, thisArg])

Array.prototype.forEach()

  • forEach() 方法对数组的每个元素执行一次提供的函数。
  • forEach 遍历的范围在第一次调用 callback 前就会确定。调用forEach 后添加到数组中的项不会被 callback 访问到。
  • forEach 方法按升序(索引)为数组中含有效值的每一项执行一次callback 函数,那些已删除(使用delete方法等情况)或者未初始化的项将被跳过(但不包括那些值为 undefined 的项)(例如在稀疏数组上)。
  • forEach() 为每个数组元素执行callback函数;不像map() 或者reduce() ,它总是返回 undefined值,并且不可链式调用。
  • 没有办法中止或者跳出 forEach 循环,除了抛出一个异常。如果你需要这样,使用forEach()方法是错误的,你可以用一个简单的循环作为替代。如果您正在测试一个数组里的元素是否符合某条件,且需要返回一个布尔值,那么可使用 Array.every 或 Array.some。如果可用,新方法 find() 或者findIndex() 也可被用于真值测试的提早终止。

语法:

array.forEach(callback[, thisArg])

Array.prototype.map()

  • map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
  • 使用 map 方法处理数组时,数组元素的范围是在 callback 方法第一次调用之前就已经确定了。

语法:

var new_array = arr.map(function callback(currentValue, index, array) { // Return element for new_array }[, thisArg])

Array.prototype.some()

  • some() 方法测试数组中的某些元素是否通过由提供的函数实现的测试。

语法:

arr.some(callback[, thisArg])

Array.from()

  •  Array.from() 方法从一个类似数组或可迭代的对象中创建一个新的数组实例。
const bar = ["a", "b", "c"];
Array.from(bar);

Array.from('foo');

let s = new Set(['foo', window]); 
Array.from(s); 

let m = new Map([[1, 2], [2, 4], [4, 8]]);
Array.from(m); 

function f() {
  return Array.from(arguments);
}

f(1, 2, 3);

Array.from([1, 2, 3], x => x + x);

Array.of()

  • Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
Array.of(7);       // [7] 
Array.of(1, 2, 3); // [1, 2, 3]

Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]

Array.fill()

  • fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。

语法:

arr.fill(value) 
arr.fill(value, start) 
arr.fill(value, start, end)

Array.find()

  • compared with Array.filter()

 Array.prototype.reduce()

语法:

array.reduce(function(accumulator, currentValue, currentIndex, array), initialValue)
参数:
callback
执行数组中每个值的函数,包含四个参数
accumulator
上一次调用回调返回的值,或者是提供的初始值(initialValue)
currentValue
数组中正在处理的元素
currentIndex
数据中正在处理的元素索引,如果提供了 initialValue ,从0开始;否则从1开始
array
调用 reduce 的数组
initialValue
可选项,其值用于第一次调用 callback 的第一个参数。如果没有设置初始值,则将数组中的第一个元素作为初始值。空数组调用reduce时没有设置初始值将会报错。

返回值

函数累计处理的结果

七、Promise(重点)

  • Promise 对象表示一个异步操作的最终完成(或失败)情况。

太抽象,先找篇文章看看:http://www.cnblogs.com/lvdabao/p/es6-promise-1.html,直接从使用的角度出发。

首先,new 一个Promise

function runAsync(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            console.log('执行完成');
            resolve('随便什么数据');
        }, 2000);
    });
    return p;            
}
runAsync()

例一:

//请求某个图片资源
function requestImg(){
    var p = new Promise(function(resolve, reject){
        var img = new Image();
        img.onload = function(){
            resolve(img);
        }
        img.src = 'xxxxxx';
    });
    return p;
}

//延时函数,用于给请求计时
function timeout(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject('图片请求超时');
        }, 5000);
    });
    return p;
}

Promise
.race([requestImg(), timeout()])
.then(function(results){
    console.log(results);
})
.catch(function(reason){
    console.log(reason);
});

解析:requestImg函数会异步请求一张图片,我把地址写为"xxxxxx",所以肯定是无法成功请求到的。timeout函数是一个延时5秒的异步操作。我们把这两个返回Promise对象的函数放进race,于是他俩就会赛跑,如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息。

例二:

Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});

解析:用Promise.all来执行,all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。那么,三个异步操作返回的数据哪里去了呢?都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then,就是上面的results。当页面有个需求,需要同时完成2个以上的ajax请求,就可以这样。

例三:

runAsync1()
.then(function(data){
    console.log(data);
    return runAsync2();
})
.then(function(data){
    console.log(data);
    return '直接返回数据';  //这里直接返回数据
})
.then(function(data){
    console.log(data);
});

解析:用维护状态、传递状态的方式来使得回调函数能够及时调用

not very well to understant them

原文地址:https://www.cnblogs.com/Merrys/p/7106945.html