es6的一些新特性

本文详细介绍了ES6的多项新特性,包括let和const声明变量、幂运算符、默认参数值、Array.find()和findIndex()方法、class类的定义与继承、Set和Map数据结构的使用、箭头函数的特性和限制、增强的对象字面量、字符串模板、解构赋值、参数默认值、不定参数和拓展参数、for of循环、模块系统、Proxies的监听能力、Symbols的唯一性和Promises的异步处理。

1. let

let 语句允许使用块作用域声明变量。

console.log(a);
    let a = 4;
    // a is not defined

2. const

将所有字母都大写的变量约定为常量,但本质还是变量 ####1.const定义只是地址不能修改

   const NUM = 100;
    NUM = 200;
    // Assignment to constant variable.

由const定义的常量,无法修改其地址值。 在这里为啥要强调是地址值 因为 以下代码在非严格模式下是可以通过的

  const OBJ = {a: 100};
    OBJ.a = 200;
    console.log(OBJ.A);
    // 200

这时候会发现这很坑啊!!! 怎么办呢,如果我们想要定义一个常量对象呢

   const OBJ = {a: 100};
    Object.freeze(OBJ);
    OBJ.a = 200;
    console.log(OBJ.a);
    // 100

这样就可以了…

3. 幂 (**)

指数运算符----取幂运算符(**)将第一个操作数提升到第二个操作数的幂。
x ** y 的结果与 Math.pow(x,y) 相同:

4. 默认参数值

ES6 允许函数参数具有默认值。

function myFunction(x, y = 10) {
  // y is 10 if not passed or undefined
  return x + y;
}
myFunction(5); // 将返回 15

5. Array.find()

find() 方法返回通过测试函数的第一个数组元素的值。

此例查找(返回)第一个大于 18 的元素(的值):

var numbers = [4, 9, 16, 25, 29];
var first = numbers.find(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

6. Array.findIndex()

findIndex() 方法返回通过测试函数的第一个数组元素的索引。
此例确定大于 18 的第一个元素的索引:

var numbers = [4, 9, 16, 25, 29];
var first = numbers.findIndex(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

老生常谈的闭包问题 实质上就是为了解决没有块级作用域带来的问题。
闭包

* 外部函数(作用域)中有内部函数(作用域)
* 内部函数调用了外部函数的局部变量
* 外部函数执行完后,因为内部函数还在使用该局部变量,所以该局部变量不被释放,保证内部函数正常使用
* 闭包函数(立即执行函数)为
    (function(){
    //  ...函数体
    })();
 var aLi = document.getElementsByTagName('li');// len = n
    for(var i = 0; i < aLi.length; i++){
        aLi[i].onclick = function(){
            console.log(i);
        }
    }
    // n......n
   var aLi = document.getElementsByTagName('li');// len = n
    for(var i = 0; i < aLi.length; i++){
        (function(i){
            aLi[i].onclick = function(){
                console.log(i);
            }
        })(i)
    }
    // 0、1、2....n

for循环实质可以理解为 由n个”{}”构成的,在每个花括号中,let的作用域都是独立的,所以可以拿到每个i值。 但对于var来说实质是一个作用域,所以无法保留每个i的值。

三、class类 在es6之前,我们要定义一个类,只能通过function来模拟

 function Person(){
        this.name = 'xxx';
    }
    Person.prototype.say = function(){
 
    }
    var person = new Person();
复制代码

问:将属性放在原型中会怎么样? 如 Person.prototype.name = ‘xxx’; 答:对于普通数据类型,没有问题,但对于引用类型,对一个对象的修改,会影响所有继承该类的对象。

1.语法

 class Person{
        constructor(name){
            this.name = name;
        }
        say() {
            console.log(this.name);
        }
    }
    var person = new Person();
    person.say();

2.继承的实现

    class Man extends Person{
        constructor(name, food){
            super(name, food); // 必须放在构造器的第一行,代表调用父类的构造方法
            this.food = food;
        }
        eat(){
            console.log(this.food);
        }
    }
    var man = new Man();
    man.say();

3.static 静态方法/变量

 class Person{
        constructor(){
        }
        static say(){
            console.log(123); // 可以认为这是一个静态方法
        }
        static name(){
            return 'xxx'; // 可以认为这是一个静态变量
        }
    }
    Person.say();

四、set集合

Set是一个不能有重复元素的集合,重复添加无效

    var s = new Set();
    s.add(1);
    s.add(2);
    // s.delete(2)  删除
    // s.clear() 清空
    // s.size() 长度

1.遍历Set

 var keys = s.keys(); // 返回一个迭代器
    for(var k of keys){
        console.log(k);
    }
 
    var values = s.values();
    for(var v of values){
        console.log(v);
    }
 
    var entries = s.entries(); // 将key和value 组合成一个数组返回
    for(var e of entries){
        console.log(e);
    }

2.es6之前Array数组去重问题 方法一:

 var arr = [1,2,3,4,1,1,1];
    function fn(arr){
        var map = {};
        var newArr = arr.filter(function(item, index){
            if(!map[item]){
                map[item] = true;
                return item;
            }
        });
        return newArr;
    }
    fn(arr);

方法二:

    var arr = [1,2,3,4,1,1,1];
    function fn(arr){
        var newArr = [];
        for(var i = 0; i < arr.length; i++){
            if(newArr.indexOf(arr[i]) === -1){
                newArr.push(arr[i]);
            }
        }
        return newArr;
    }
    fn(arr);

利用Array.from的方法三:

  var arr = [1,2,3,4,1,1,1];
    function fn(arr){
        var s = new Set(arr);
        return Array.from(s);
    }
    fn(arr);

3.Array返回只出现一次的元素

   var arr = [1,2,3,4,1,1,1];
    function fn(arr){
        var newArr = [];
        for(var i = 0; i < arr.length; i++){
            if(arr.indexOf(arr[i]) === arr.lastIndexOf(arr[i])){
                newArr.push(arr[i]);
            }
        }
        return newArr;
    }
    fn(arr);

五、Map(键值对)

  var m = new Map();
    m.set('a',1);
    m.set('b',2);
    m.get('a'); // 1
 
    // m.delete('a')

对象的属性名 认为是字符串,但Map的键 可以是所有数据类型

forEach可以遍历Array、Set、Map。 
for of被专门用来遍历迭代器。
复制代码

六、arrow 箭头函数

终于来到了箭头函数的环节()=>{} 这是一种特别简洁、优雅的函数写法 它可以这么写

 var fn = (item, index) => {console.log(item)}

也可以这么写

 var fn = item => {console.log(item)}

还可以这么写

 var fn = item => (item)
    fn(2) // 2

=>后使用小括号() 表示将结果作为返回值,单行结果时还可以省略 当参数唯一时,还可以将前面的() 省略 但是他失去了一些东西…

 var fn = () => {
        console.log(arguments);
    }
    fn(2) // arguments is not defined

解决方法如下:

   var fn = (...arg) => {
        console.log(arg);
    }
    fn(2) // [2]

箭头函数不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

箭头函数会改变默认的this指向

箭头函数能够将函数外面的this指向同步到函数内部,比如说这样:

   var aLi = document.getElementsByTagName('li');// len = n
    for(var i = 0; i < aLi.length; i++){
        aLi[i].onclick = function(){
            setTimeout(function(){
                console.log(this.innerHTML);
                // 此时无法获取,因为this指向调用他的对象,而setTimeout为window下的方法,此时this指向window
            })
        }
    }

将function改为箭头函数就能够正确运行

    var obj = {
        a: 1,
        say: function(){
            console.log(this.a);
        }
    }
    obj.say() // 1

上面乍一看这个挺正常的结果呀… 但是如果改成箭头函数

   var obj = {
        a: 1,
        say: () => {
            console.log(this.a);
        }
    }
    obj.say() // undefined

所以箭头函数虽好,也要看清场合使用啊。

七、增强的对象字面量

对象字面量被增强了,写法更加简洁与灵活,同时在定义对象的时候能够做的事情更多了。具体表现在:

1、可以在对象字面量里面定义原型 2、定义方法可以不用function关键字 3、直接调用父类方法 这样一来,对象字面量与前面提到的类概念更加吻合,在编写面向对象的JavaScript时更加轻松方便了。

//通过对象字面量创建对象
var human = {
    breathe() {
        console.log('breathing...');
    }
};
var worker = {
    __proto__: human, //设置此对象的原型为human,相当于继承human
    company: 'freelancer',
    work() {
        console.log('working...');
    }
};
human.breathe();//输出 ‘breathing...
//调用继承来的breathe方法
worker.breathe();//输出 ‘breathing...

八、字符串模板

字符串模板相对简单易懂些。ES6中允许使用反引号 ` 来创建字符串,此种方法创建的字符串里面可以包含由美元符号加花括号包裹的变量${vraible}。

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

九、解构

自动解析数组或对象中的值。比如若一个函数要返回多个值,常规的做法是返回一个对象,将每个值做为这个对象的属性返回。但在ES6中,利用解构这一特性,可以直接返回一个数组,然后数组中的值会自动被解析到对应接收该值的变量中。

var [x,y]=getVal(),//函数返回值的解构
    [name,,age]=['wayou','male','secrect'];//数组解构
 
function getVal() {
    return [ 1, 2 ];
}
 
console.log('x:'+x+', y:'+y);//输出:x:1, y:2 
console.log('name:'+name+', age:'+age);//输出: name:wayou, age:secrect 

十、参数默认值,不定参数,拓展参数

1.默认参数值

现在可以在定义函数的时候指定参数的默认值了,而不用像以前那样通过逻辑或操作符来达到目的了。

	//传统的指定默认参数的方式
	var name=name||'dude';
	console.log('Hello '+name);
}
//运用ES6的默认参数
function sayHello2(name='dude'){
	console.log(`Hello ${name}`);
}
sayHello();//输出:Hello dude
sayHello('Wayou');//输出:Hello Wayou
sayHello2();//输出:Hello dude
sayHello2('Wayou');//输出:Hello Wayou

2.不定参数

不定参数是在函数中使用命名参数同时接收不定数量的未命名参数。这只是一种语法糖,在以前的JavaScript代码中我们可以通过arguments变量来达到这一目的。不定参数的格式是三个句点后跟代表所有不定参数的变量名。比如下面这个例子中,…x代表了所有传入add函数的参数。

//将所有参数相加的函数
function add(...x){
	return x.reduce((m,n)=>m+n);
}
//传递任意个数的参数
console.log(add(1,2,3));//输出:6
console.log(add(1,2,3,4,5));//输出:15

3.拓展参数

拓展参数则是另一种形式的语法糖,它允许传递数组或者类数组直接做为函数的参数而不用通过apply。

var people=['Wayou','John','Sherlock'];
//sayHello函数本来接收三个单独的参数人妖,人二和人三
function sayHello(people1,people2,people3){
	console.log(`Hello ${people1},${people2},${people3}`);
}
//但是我们将一个数组以拓展参数的形式传递,它能很好地映射到每个单独的参数
sayHello(...people);//输出:Hello Wayou,John,Sherlock 
 
//而在以前,如果需要传递数组当参数,我们需要使用函数的apply方法
sayHello.apply(null,people);//输出:Hello Wayou,John,Sherlock 

十一、for of 值遍历

我们都知道for in 循环用于遍历数组,类数组或对象,ES6中新引入的for of循环功能相似,不同的是每次循环它提供的不是序号而是值。

var someArray = [ "a", "b", "c" ];
 
for (v of someArray) {
    console.log(v);//输出 a,b,c
}

十二、模块

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

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

// 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);

十三、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

十四、Symbols

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

(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//无法访问该属性,因为是私有的

十五、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"
});
<think>首先,用户的问题是:“我想了解ES6的语法新特性请问ES6新增语法特性介绍”。这基于系统指令和提供的引用。系统指令要求:-所有行内数学表达式使用$...$格式。-独立公式使用$$...$$格式并单独成段。-LaTeX语法正确。-使用中文回答。-生成相关问题。-回答中引用的段落末尾自然地添加引用标识。-回答结构清晰,帮助用户逐步解决问题,保证真实可靠。参考的引用:-[^1]:提到ES6新增特性如Promise、模块化、class、箭头函数、解构赋值、let/const、Symbol。-[^2]:简要介绍ES6,提到箭头函数等。-[^3]:详细解释let和const的块级作用域。-[^4]:讨论数组新特性如扩展运算符。用户的需求是了解ES6的新增语法特性,所以我需要基于这些引用构建一个全面的回答。回答结构:1.**引言**:简要介绍ES6和其重要性。2.**逐步介绍新特性**:列出主要特性,并详细解释每个,参考引用中的信息。3.**使用引用**:自然地添加引用标识到相关段落末尾。4.**生成相关问题**:在最后添加相关问题部分。5.**确保真实可靠**:基于提供的引用和一般知识。关键特性从引用中提取:-Promise([^1])-模块化([^1])-class关键字([^1])-箭头函数([^1],[^2])-解构赋值([^1],[^4])-let和const([^1],[^3])-Symbol([^1])-数组新特性如扩展运算符([^4])我应该覆盖这些,并可能添加其他常见特性如模板字符串、默认参数等,但引用中没有提到,所以优先基于引用。回答结构:-**开头**:介绍ES6。-**主体**:逐项解释特性。-每个特性:解释是什么,为什么有用,可能举例。-**结尾**:总结。-**相关问题**:生成3-5个相关问题。使用中文回答。添加引用标识:-例如,解释Promise时,引用[^1]。-自然地添加,如“ES6新增了Promise,用于处理异步操作[^1]。”生成相关问题:-类似示例中的格式:§§相关问题§§然后列表。最终输出格式:-回答部分。-§§相关问题§§-问题列表。</think>### ES6新增语法特性介绍 ES6(ECMAScript 2015)是JavaScript语言的一次重大更新,由TC39委员会制定,它引入了许多新特性,旨在提升代码的可读性、可维护性和开发效率[^2]。ES6标志着JavaScript从脚本语言向现代编程语言的转变,为大型应用开发提供了强大工具。下面我将逐步介绍ES6的主要新增语法特性,基于可靠引用和实际应用场景,确保内容真实可靠。 #### 1. **箭头函数** - **是什么**:箭头函数(Arrow Functions)是一种简化函数定义的语法,使用`=>`符号代替传统`function`关键字。 - **为什么有用**:它简化了回调函数写法,并自动绑定`this`到外层作用域,避免传统函数中`this`指向问题[^2]。 - **示例**: ```javascript // 传统函数 const add = function(a, b) { return a + b; }; // 箭头函数简化 const addArrow = (a, b) => a + b; ``` - **与传统函数的区别**:箭头函数没有自己的`this`、`arguments`、`super`或`new.target`,适合作为匿名函数使用[^1]。 #### 2. **let和const关键字** - **是什么**:`let`和`const`用于声明变量和常量,取代了`var`的部分功能。 - **为什么有用**:`let`提供块级作用域(block scope),变量只在声明块内有效,避免了变量提升(hoisting)导致的错误[^3]。`const`用于声明常量,一旦赋值不可更改,增强了代码的不可变性[^1]。 - **示例**: ```javascript if (true) { let x = 10; // 只在if块内有效 const y = 20; // 常量,不可重新赋值 } console.log(x); // ReferenceError: x未定义 ``` - **与var的区别**:`var`只有函数作用域,容易导致全局污染;`let/const`更安全,推荐在现代代码中优先使用[^1]。 #### 3. **解构赋值** - **是什么**:解构赋值(Destructuring Assignment)允许从数组或对象中提取值,直接赋给变量。 - **为什么有用**:它简化了数据提取过程,提高了代码可读性,尤其在处理API响应或配置对象时[^1]。 - **示例**: ```javascript // 数组解构 const [a, b, ...rest] = [1, 2, 3, 4]; // a=1, b=2, rest=[3,4][^4] // 对象解构 const { name, age } = { name: "Alice", age: 30 }; ``` #### 4. **Promise** - **是什么**:Promise是一种处理异步操作的对象,代表一个可能完成或失败的操作。 - **为什么有用**:它解决了“回调地狱”问题,提供了`.then()`和`.catch()`方法链式处理异步结果,使代码更易维护[^1]。 - **示例**: ```javascript const fetchData = new Promise((resolve, reject) => { setTimeout(() => resolve("Data loaded"), 1000); }); fetchData.then(data => console.log(data)).catch(error => console.error(error)); ``` #### 5. **模块化** - **是什么**:ES6引入了原生模块系统,使用`import`和`export`语法管理代码依赖。 - **为什么有用**:它支持代码拆分和重用,便于构建大型应用,替代了CommonJS或AMD等第三方方案[^1]。 - **示例**: ```javascript // 导出模块: math.js export const add = (a, b) => a + b; // 导入模块: main.js import { add } from './math.js'; console.log(add(2, 3)); // 输出5 ``` #### 6. **class关键字** - **是什么**:`class`提供了面向对象编程的语法糖,用于定义类和继承。 - **为什么有用**:它简化了构造函数和原型链的操作,使JavaScript更接近传统OOP语言[^1]。 - **示例**: ```javascript class Person { constructor(name) { this.name = name; } greet() { return `Hello, ${this.name}!`; } } const alice = new Person("Alice"); console.log(alice.greet()); ``` #### 7. **Symbol类型** - **是什么**:Symbol是ES6新增的简单数据类型,表示唯一标识符。 - **为什么有用**:它用于创建对象属性的唯一键,避免命名冲突,尤其在库开发中[^1]。 - **示例**: ```javascript const sym = Symbol('unique'); const obj = { [sym]: 'value' }; console.log(obj[sym]); // 输出'value' ``` #### 8. **数组新特性(如扩展运算符)** - **是什么**:扩展运算符(Spread Operator)`...`允许将数组或对象展开为独立元素。 - **为什么有用**:它简化了数组复制、合并和解构赋值,提高了代码简洁性[^4]。 - **示例**: ```javascript // 复制数组 const arr1 = [1, 2, 3]; const arr2 = [...arr1]; // arr2是arr1的副本[^4] // 合并数组 const merged = [...arr1, ...arr2]; // 输出[1,2,3,1,2,3] ``` #### 总结 ES6的这些特性不仅提升了JavaScript的功能和性能,还使其更适合现代Web开发。例如,箭头函数和`let/const`增强了代码安全性,Promise和模块化支持了异步和模块化编程[^3][^2]。实际应用中,ES6已成为前端开发的标准,广泛用于React、Vue等框架。如果你有具体场景的疑问,欢迎进一步探讨!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值