ES6 语法:强大特性全解析

目录

ES5中的严格模式

JS的语法是什么灵活的,但这种灵活可能会导致全局污染,所以ES5引入了严格模式,听名字就知道这种模式下语法的要求更高,更苛刻。这样可以让JS在更严格的语法下运行,确保安全性,不合理性。

如何使用严格模式?

如果在整个文件使用,将use strict放在文件第一行。

如果在单个函数使用,将use strict放在函数第一行。

第一种方法不利于文件的合并,所以一般使用第二种放在函数第一行。

严格模式到底什么严格?

  • 全局变量显示声明

在Java中如果想声明一个全局变量需要在方法外定义,但ES5的正常模式中无需声明就赋值的变量就是全局变量,严格模式中禁止了这样的用法。

javascript 复制代码
//不使用严格模式就是正确的
v = 1;
  • 静态绑定

Javascript语言的一个特点,就是允许"动态绑定",即某些属性和方法到底属于哪一个对象,不是在编译时确定的,而是在运行时(runtime)确定的。

严格模式对动态绑定做了一些限制。某些情况下,只允许静态绑定。也就是说,属性和方法到底归属哪个对象,在编译阶段就确定。这样做有利于编译效率的提高,也使得代码更容易阅读,更少出现意外。

javascript 复制代码
//(1)禁止使用with语句,使用严格模式后下面的例子就不能成功运行。
var obj = {
    x: 10,
    y: 20
};
with (obj) {
    console.log(x); // 这里会输出10,因为在obj对象的属性中找到了x
}

//(2)创设eval作用域,JavaScript中有全局作用域和函数作用域,严格模式下有了eval作用域。
   var x = 2;
  console.info(eval("var x = 5; x")); // 5
  console.info(x); // 2
  • 增强的安全措施

禁止this关键字指向全局对象

javascript 复制代码
	function f(){
    return !this;
  }
  // 返回false,因为"this"指向全局对象,"!this"就是false

  function f(){
    "use strict";
    return !this;
  }
  // 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。

禁止在函数内部遍历调用栈

在正常模式下可以通过caller获取当前函数的引用,arguments可以获取传入当前函数的参数列表

javascript 复制代码
	function f1(){

    "use strict";

    f1.caller; // 报错

    f1.arguments; // 报错

  }
  f1();
  • 禁止删除变量

严格模式禁止删除变量除非configurable设置为true的对象属性。

javascript 复制代码
	"use strict";

  var x;

  delete x; // 语法错误

  var o = Object.create(null, {'x': {
      value: 1,
      configurable: true
  }});

  delete o.x; // 删除成功
  • 显式报错

对一个对象的只读属性进行赋值,将报错。

对一个使用getter方法读取的属性进行赋值,会报错。

对禁止扩展的对象添加新属性,会报错。

删除一个不可删除的属性,会报错。

  • 函数必须声明在顶层

将来Javascript的新版本会引入"块级作用域"。为了与新版本接轨,严格模式只允许在全局作用域或函数作用域的顶层声明函数。也就是说,不允许在非函数的代码块内声明函数。

ES6中的let、const和块级作用域

在ES6中使用let代替ES5中的var去定义变量,const用来定义常量。我将分别举个例子来讲述他们三个的区别。

var

javascript 复制代码
var a = 1;
{
    var a = 2;
}

console.log(a); //输出2

这段代码输出结果为2,这让一个之前学java的人很震惊。

这段代码说明var定义变量不具备块级作用域特性。var定义的变量是全局性的,容易造成全局污染。

let

let的语法跟java的语法一样,在一个{}(作用域)中定义的变量只能在该作用域使用,离开该作用域访问将报错。

const

一些变量是确定的,声明之后不想被改变就用const定义,当然const定义的常量和let定义的变量都只能在块级作用域中起作用,出了块之后无法访问。

ES6中变量的解构赋值

解构赋值:解析结构,赋予值。(从数组或者对象中提取值然后按一一对应的方式赋给变量)

数组中的解析赋值

在ES6之前当我们想为一组变量赋值:

javascript 复制代码
var a = 1;
var b = 2;
var c = 3;
//or
var arr = [1, 2, 3];

var a = arr[0];
var b = arr[1];
var c = arr[2];

在ES6中我们可以直接这样进行一组变量的赋值。

javascript 复制代码
let [a, b, c] = [1, 2, 3];
  • 当左边变量大于右边值,剩余变量会被赋值为undefined
  • 解析赋值时变量允许有默认值。 let [a, b = 'iyaovo'] = ['wzy']; 这样b没有匹配到东西也有默认值

对象的解构赋值

在ES6之前,当我们调用api接口拿到数据后我们要这样赋值:

javascript 复制代码
var name = json.name;
var age = json.age;
var sex = json.sex;

现在我们可以解构赋值,直接将一个对象赋值给一组属性,会按照键取值(不像数组是按顺序的)。

javascript 复制代码
const person = { name: 'iyaovo', age: 21, sex: '男' };
let { name, age, sex } = person; 

那么,左边的变量名必须和右边对象的属性名一致吗?

javascript 复制代码
const person = { name: 'iyaovo', age: 21 };
let { name: myName, age: myAge } = person; 
//:左边的对应对象中的属性名,:右边的是定义变量的名字
console.log(myName); 
console.log(myAge); 

ES6中箭头函数

箭头函数语法

javascript 复制代码
(参数1, 参数2 ...) => {  }
  • 如果有且只有一个形参,那么括号可以省略。 参数 => {}
  • 如果函数体中只有一条语句,那么{}可以省略。但这条语句必须是return语句

箭头函数是没有箭头名的,你可以直接调用它,或者将它赋给一个变量,通过变量调用它。

这个语法类似Java中的钻石表达式。

例子

javascript 复制代码
//标准写法
const fn = (a, b) => {
    console.log('这是标准');
    return a + b;
};
console.log(fn(1, 2));

//精简写法
const fn = a => a + 1;
console.log(fn(1));

箭头函数的this的指向

ES6 之前的普通函数中:this 指向的是函数被调用的对象(也就是说,谁调用了函数,this 就指向谁)。

而 ES6 的箭头函数中:箭头函数本身不绑定 this ,this 指向的是箭头函数定义位置的 this(也就是说,箭头函数在哪个位置定义的,this 就跟这个位置的 this 指向相同)。

javascript 复制代码
function fn1() {
    console.log(this); // 第一个 this
    return () => {
        console.log(this); // 第二个 this
    };
}

箭头函数是在fn1里定义的,所以箭头函数中的this和fn1this的指向一致。

参数默认值

javascript 复制代码
function fn(param = 'hello') {
    console.log(param);
}

直接在形参的位置指定了参数默认值。

字符串、数组、对象的扩展

字符串的扩展
  • includes(str)

用于判断当前字符串中是否包含指定的字符串 str,返回值为布尔类型,区分大小写。

javascript 复制代码
let str = "Hello, world!";
console.log(str.includes("world")); // true,因为原字符串包含"world"这个子串
console.log(str.includes("World")); // false,区分大小写,原字符串中没有"World"
  • startsWith(str)

判断当前字符串是否以指定字符串 str 开头,同样返回布尔值,区分大小写。

javascript 复制代码
let str = "JavaScript is great";
console.log(str.startsWith("Java")); // true,原字符串以"Java"开头
console.log(str.startsWith("java")); // false,区分大小写,原字符串不以"java"开头
  • endsWith(str)

判断当前字符串是否以指定字符串 str 结尾,返回布尔值(true 结尾返回 true,反之返回 false),同样区分大小写。

javascript 复制代码
let str = "This is a sample text.";
console.log(str.endsWith("text.")); // true,原字符串以"text."结尾
console.log(str.endsWith("Text.")); // false,区分大小写,原字符串不以"Text."结尾
  • repeat(count)

将当前字符串重复指定的次数 count 并返回新的字符串。参数 count 必须是一个大于等于 0 的整数,如果传入的是小数或者负数等不符合要求的值,会抛出错误。

javascript 复制代码
let str = "abc";
console.log(str.repeat(3)); // "abcabcabc",原字符串重复3次
console.log(str.repeat(0)); // "",重复0次返回空字符串
// 以下情况会报错,比如传入小数
// console.log(str.repeat(2.5)); // 会抛出错误,参数要求是整数
数组的扩展
  • Array.from ()

用于将两类对象转换为真正的数组:类似数组的对象(有length属性和索引属性)和可迭代对象(如SetMap等)。它返回一个新的数组实例。

  • 第一个参数是必需的,它是一个类似数组的对象或可迭代对象,要被转换为数组的对象。
  • 第二个参数是一个可选的映射函数,类似于数组的map方法,用于对转换后的每个元素进行处理,该函数会接收三个参数:当前元素、当前元素的索引和正在构建的新数组。
  • 第三个参数也是可选的,它用于指定map函数中的this指向。
javascript 复制代码
//单一参数(类似数组的对象)
let arrayLike = {
    0: 'a',
    1: 'b',
    length: 2
};
let newArray = Array.from(arrayLike);
console.log(newArray); // ["a", "b"]

//可迭代对象
let mySet = new Set([1, 2, 3]);
let setToArray = Array.from(mySet);
console.log(setToArray); // [1, 2, 3]

//String也是可迭代对象
let str = "hello";
let strToArray = Array.from(str);
console.log(strToArray); // ["h", "e", "l", "l", "o"]

//使用映射函数
let arrayLike2 = {
    0: 1,
    1: 2,
    length: 2
};
let newArray2 = Array.from(arrayLike2, (x) => x * 2);
console.log(newArray2); // [2, 4]
  • Array.find()

find()是数组的一个实例方法,用于在数组中查找满足给定条件的第一个元素。如果找到符合条件的元素,就返回该元素;如果遍历完整个数组都没有找到符合条件的元素,则返回undefined

参数:

callback必需。这是一个回调函数,用于定义查找条件。它接收三个参数:

  • element:当前正在被处理的元素。
  • index:当前元素的索引(可选参数)。
  • array:调用find()方法的原始数组(可选参数)。

thisArg:可选。用于执行callback函数时的this对象。

javascript 复制代码
//在一个简单的数字数组中查找第一个大于 10 的元素。
let numbers = [5, 12, 8, 15];
let foundNumber = numbers.find((element) => element > 10);
console.log(foundNumber); // 12

let users = [
    {id: 1, name: 'Alice'},
    {id: 2, name: 'Bob'},
    {id: 3, name: 'Charlie'}
];
let foundUser = users.find((user) => user.id === 2);
console.log(foundUser); // {id: 2, name: "Bob"}
对象的扩展
  • Object.is()

    判断两个数据是否相等,底层是通过字符串来判断的

javascript 复制代码
console.log(NaN == NaN); //如果用等号比,不相等,因为NaN和任何值都不相等
console.log(Object.is(NaN, NaN)); //如果用is方法比,是通过字符串去比,那它俩就相等
  • Object.assign()

它将一个或多个源对象的可枚举属性复制到目标对象,并返回目标对象。如果目标对象和源对象有同名属性,那么后面的属性会覆盖前面的属性。

参数

  • target:目标对象,是接收属性的对象,必须是对象类型。
  • sources:一个或多个源对象,是提供属性的对象,这些对象也必须是对象类型。可以有多个源对象,它们的属性会按照顺序依次被复制到目标对象中。
javascript 复制代码
//简单对象合并,Object.assign()修改了目标对象targetObj,并且返回值也是修改后的目标对象。
let targetObj = {a: 1};
let sourceObj = {b: 2};
let result = Object.assign(targetObj, sourceObj);
console.log(targetObj); // {a: 1, b: 2}
console.log(result); // {a: 1, b: 2}

//多次合并,后面的属性会覆盖前面的。
let obj1 = {a: 1, b: 2};
let obj2 = {b: 3, c: 4};
let obj3 = {d: 5};
let mergedObj = Object.assign({}, obj1, obj2, obj3);
console.log(mergedObj); // {a: 1, b: 3, c: 4, d: 5}

**注意:**该方法的拷贝是浅拷贝。

javascript 复制代码
let sourceObj = {
    nested: {
        value: 1
    }
};
let targetObj = {};
let result = Object.assign(targetObj, sourceObj);
result.nested.value = 2;
console.log(sourceObj.nested.value); // 2

可以看出,使用拷贝好的对象更改内部值,源对象的内部值也被改变。

Set数据结构

ES6 提供了 新的数据结构 Set。Set 类似于数组 ,但成员的值都是唯一的,没有重复的值。

创建 Set 实例

javascript 复制代码
let mySet = new Set([1, 2, 3, 3]);
console.log(mySet); // Set(3) {1, 2, 3},注意3只出现了一次,因为Set中的元素是唯一的

Set 的基本操作方法

add

javascript 复制代码
let set1 = new Set();
set1.add(1);
set1.add(2);
set1.add(1);
console.log(set1); // Set(2) {1, 2},第二次添加1没有效果,因为Set中的元素具有唯一性

delete

javascript 复制代码
let set2 = new Set([1, 2, 3]);
console.log(set2.delete(2)); // true
console.log(set2); // Set(2) {1, 3}
console.log(set2.delete(4)); // false

has

javascript 复制代码
let set3 = new Set([5, 6, 7]);
console.log(set3.has(6)); // true
console.log(set3.has(8)); // false

clear

javascript 复制代码
let set4 = new Set([9, 10, 11]);
set4.clear();
console.log(set4); // Set(0) {}

遍历set

javascript 复制代码
let set5 = new Set(['a', 'b', 'c']);
for (let key of set5.keys()) {
    console.log(key);
}
// 输出:
// a
// b
// c
for (let value of set5.values()) {
    console.log(value);
}
// 输出:
// a
// b
// c
for (let [key, value] of set5.entries()) {
    console.log(key, value);
}
// 输出:
// a a
// b b
// c c

参考

千古前端图文教程

相关推荐
还是鼠鼠2 小时前
图书管理系统 Axios 源码 __删除图书功能
前端·javascript·vscode·ajax·前端框架·node.js·bootstrap
轻口味2 小时前
Vue.js `Suspense` 和异步组件加载
前端·javascript·vue.js
m0_zj3 小时前
8.[前端开发-CSS]Day08-图形-字体-字体图标-元素定位
前端·css
还是鼠鼠3 小时前
图书管理系统 Axios 源码__编辑图书
前端·javascript·vscode·ajax·前端框架
北极象3 小时前
vue3中el-input无法获得焦点的问题
前端·javascript·vue.js
百度网站快速收录4 小时前
网站快速收录:如何优化网站头部与底部信息?
前端·html·百度快速收录·网站快速收录
Loong_DQX4 小时前
【react+redux】 react使用redux相关内容
前端·react.js·前端框架
GISer_Jing4 小时前
react redux监测值的变化
前端·javascript·react.js
engchina4 小时前
CSS 样式化表格:从基础到高级技巧
前端·css
m0_528723814 小时前
react中useEffect的使用
前端·javascript·react.js