Es6--ECMAScript 新增语法

发布于:2025-04-07 ⋅ 阅读:(30) ⋅ 点赞:(0)

一、对象字面量扩展

1、属性的定义

ES6之前

1
2
3
4
5
6
var name = 'zs';
var age = 18;

var user = {"name":name,"age":age} ;

console.log(user);

ES6之后

1
2
3
4
5
6
7
8
var name = 'zs';
var age = 18;

// 生成的user对象中,属性名就是变量名,属性值为对应变量的值。
// 当然,必须先定义相关的变量
var user = {name,age} ;

console.log(user);

2、方法的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var user = {
  // ES6之前
  eat:function() {
    console.log('吃');
  },

  // ES6后,省略冒号和functon关键字
  sleep() {
    console.log("睡觉");
  }

}

user.eat() ;
user.sleep() ;

3、属性表达式

ES6之前

访问属性和方法有两种方式,分别为:

  • 点操作符
    • 对象.属性
    • 对象.方法()
  • []操作符
    • 对象[属性名]
    • 对象[方法名]()
    • 注意,中括号中的名称支持使用表达式运算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var user = {
  user_name: 'zs',
  user_age: 18,
  user_login: function () {
    console.log('登录');
  }
}

// 在中括号中,编写表达式,连接字符串,访问相关的属性和方法

// 点操作符
console.log(user.user_name);

// 中括号操作,支持表达式运算
console.log(user['user_' + 'age']);	
user['user_' + 'login']();

ES6之后

对象的属性定义,支持使用表达式进行运算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 定义前缀字符串
var prefix = 'user_' ;

var user = {
  // 定义属性时,支持使用表达式运算
  [prefix+'name']: 'zs',
  [prefix+'age']: 18,
  [prefix+'login']: function () {
    console.log('登录');
  }
}

// 在中括号中,编写表达式,连接字符串,访问相关的属性和方法
console.log(user.user_name);
console.log(user['user_' + 'age']);

user['user_' + 'login']();

4、属性访问器

简化了Object.defineProperty()的存取数据描述的定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var user = {
  // 访问时,直接访问age即可,而_age是一种编程规范,并没有实现对外隐藏,外部依然可以直接访问
  _age:0,

  get id() {
    return this._age ;
  },

  set id(value) {
    this._age = value ;
  }
} 

user.age = 18 ;
console.log(user.age);

5、直接指定原型

1
2
3
4
5
6
7
8
9
10
11
var person = {
  name:'匿名'
}

var user = {
  // 直接通过 __proto__ 属性指定原型对象
  __proto__:person
} 

console.log(user);
console.log(user.name);

__proto__属性已在ES6中标准化。在文本标记法中,__proto__只是语法糖,可以方便的指定原型对象。本质上还是使用构造方法的prototype属性来指定原型对象的,即Object.prototype

另外,以下方法,也可以指定原型对象

1
2
3
4
5
6
var user1 = {}
Object.setPrototypeOf(user1,person);
console.log(user1);

var user2 = Object.create(person) ;
console.log(user2);

6、super关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var animal = {
  name:'动物' ,
  show() {
    // 输出当前对象,查看this的指向
    console.log(this);
    console.log('我是一只 ' + this.name);
  }
}

var cat = {
  // 直接通过 __proto__ 属性指定原型对象
  __proto__:animal ,
  // 覆盖属性
  name:'猫',
  show() {
    // 调用原型中的方法,有以下三种方式
    // 方式一:在原型的show()方法中,this指向的还是cat对象
    // super.show() ;

    // 方式二:区别于super,在原型的show()方法中,this的还是cat对象
    // Object.getPrototypeOf(this).show() ;

    // 方法三:使用call方法调用,重新指定this的指向,使其指定cat对象,完全等同于super。
    // 因此,super是一个语法糖,方便调用
    Object.getPrototypeOf(this).show.call(this) ;

    console.log('喵喵...');
  }
} 

cat.show() ;

二、块级作用域

1、Hoisting

变量和函数的提升(Hoisting),是JavaScript中执行上下文(特别是创建和执行阶段)一种特殊的工作方式。

1)变量提升
1
2
3
4
5
6
7
8
// undefined
console.log(a);	

// b is not defined
console.log(b);

var a = 100 ;
b = 200 ;

在JavaScript中,var声明的变量具有Hoisting特性,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面。上面代码编译后的结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
// var声明的变量具有Hoisting特性,会在程序最前面进行声明,并初始值为undefined
var a = undefined;

// undefined
console.log(a);	

// b is not defined
console.log(b);

a = 100 ;

// 未使用var声明的变量,不具有Hoisting特性
b = 200 ;
2)函数提升
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fun1() ;

console.log(fun2);
fun2() ;


// 声明函数
function fun1() {
  console.log('fun1');
}

// var定义的函数表达式 -- 文本标记定义,与变量var声明一样
var fun2 = function() {
  console.log('fun2');
}

声明的函数具有hoisting特性,而var定义的函数表达式与变量一样会提升且赋值为undefined。上面代码编译后的结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 声明式函数会提升在最前面
function fun1() {
  console.log('fun1');
}

// 与变量声明一样,var声明的函数会提升在前面,且初始值为undefined
var fun2 = undefined ;

// 成功调用
fun1() ;

// 输出undefined
console.log(fun2);

// 因为fun2现在为undefined,因此报错
fun2() ;

注意:函数和变量的提升中,函数优秀级更高一点,即函数要比变量的提升到更高的位置。

2、let

var一样,是用于声明变量的关键字(ES6新增)

1)作用域

let声明的变量支持块级作用域,只作用于当前块

1
2
3
4
5
6
7
if(true) {
 	var m = 100 ;
  let n = 200 ;
}

console.log(m) ;
console.log(n) ;
2)变量提升

let声明的变量不会被”提升”

1
2
3
4
// undefined
console.log(m) ;

let m = 100 ;
3)重复定义

let不允许重复定义相同的变量

1
2
3
4
let m = 100 ;
let m = 100 ;

// var可以,后者覆盖前者
4)暂时性死区

利用let声明的变量会绑定在这个块级作用域,不会受外界的影响。

1
2
3
4
5
6
7
8
9
10
11
var tmp = 123;
if (true) { 
  tmp = 'abc';
  
  // 思考:输出结果为?why?
  // console.log(tmp);
  
  let tmp; 
} 
// 思考2:输出结果为?why?
// console.log(tmp) ;

暂时性死区指的是在当前作用域中,在使用 let 声明变量之前访问该变量会抛出 ReferenceError 错误,即使变量使用var声明也不例外。

也就是说,使用letconst声明的变量,只有在声明语句之后才能被访问。

思考题

1
2
3
4
5
6
7
8
9
10
var arr = [];
for (var i = 0; i < 2; i++) {
  arr[i] = function () {
    console.log(i); 
  }
}

// 以下两行代码,输出结果为?
arr[0]();
arr[1]();

let面试题

说明:变量i是全局的,在调用函数之前,循环已经执行完毕,此时的循环变量的值为2。因此,在调用函数时,函数使用的变量i是最新的值。

1
2
3
4
5
6
7
8
9
10
11
12
let arr = [];

// let声明的变量i,在循环中都会产生一个块级作用域
for (let i = 0; i < 2; i++) {
  arr[i] = function () {
    console.log(i); 
  }
}

// 以下两行代码,输出的结果为?
arr[0]();
arr[1]();

let面试题2

说明:let关键字声明的变量具有块级作用域。每次循环都会产生一个块级作用域,每个块级作用域中的变量都是不同的。因此,调用函数时输出对应作用域下的i值。

课堂练习

在页面中,定义以下的无序列表:

  • 你好
  • 我好
  • 大家好,才是真的好

编写JS,实现当用户单击以上无序列表时,弹出对应的文本内容及其下标索引。

提示:var实现 、let实现、闭包实现

3、const

声明常量,常量就是值(内存地址)不能变化的量。

1
2
// 在声明常量的同时,必须初始化值,且值在后面的使用中不能改变
const 常量名称 = 值 ;

const与let基本相同,产生块级作用域,不会提升,存在暂时性死区,必须先声明后使用,不允许重复定义。

const限制的只是常量指向的内存地地不变,但地址所引用的对象是允许被修改的。因为简单类型的数据直接存放在内存地址中,而复杂类型(如对象各数组)的数据是间接存储的。如:

1
2
3
4
5
6
7
8
9
10
// 定义一个常量数组
const LIST = [100, 200];

LIST.push(300);

// 常量对应的数组是允许进行相关的操作
console.log(LIST);

// 错误,常量不允许重新赋值
LIST = [100,200,300]; 

小结

  • const用于声明常量

  • 在声明常量的同时,必须初始值

  • 常量不能重新进行赋值

    • 如果是基本数据类型,不能更改值;
    • 如果是复杂数据类型,不能更改地址值,但复杂类型的数据是允许修改的。

4、var、let、const区别

  • 使用 var 声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象
  • 使用 let 声明的变量,其作用域为该语句所在的代码块内,不存在变量提升
  • 使用 const 声明的是常量,在后面出现的代码中不能再修改该常量的值

三、函数默认值

1、默认参数值

ES6之前

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function fun(m, n) {
  // 参数默认值处理
  m = m || 100 ;
  n = n || 200 ;

  console.log('m=' + m + ',n=' + n);
}

fun(1) ;
fun(1,2) ;
fun(1,undefined) ;
fun(undefined,2) ;

// 结果为?
fun(0,0) ;

ES6之后

在声明函数时,允许直接把默认值定义在形参中,如:

1
2
3
4
5
6
7
8
9
10
11
12
// 设置参数的默认值
function fun(m=100, n=200) {
  console.log('m=' + m + ',n=' + n);
}

fun(1) ;
fun(1,2) ;
fun(1,undefined) ;
fun(undefined,2) ;

// 结果为?
fun(0,0) ;

如果没有传递实参,则使用默认值,否则使用传递的实参数据。

2、默认值表达式

1)函数默认值支持表达式运算
1
2
3
4
5
6
7
// 设置参数的默认值
function fun(m=100*2, n=200+m) {
  console.log('m=' + m + ',n=' + n);
}

// 结果为?
fun() ;
2)函数默认值为自调用函数
1
2
3
4
5
6
7
8
function fun(m=100*2, n=(function(v){
  return v + 200
})(200)) {

  console.log('m=' + m + ',n=' + n);
}

fun() ;

四、spread与rest

1、spread:展开

语法:…名称

注意:

  • 名称必须是一个可iterable的对象。
  • 其中可iterable的对象有:数组、字符串、生成器(Generators)、集合(Collections)
  • 作用:把可iterable的对象展开,并返回展开的内容
1)数组操作
1
2
3
4
5
6
var arr1 = [1, 2, 3];

// 展开arr1数组,并把展开的内容添加到arr2中
var arr2 = ['AA', ...arr1, 'BB'];

console.log(arr2);
2)对象操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var obj1 = {name:'zs',age:18}

var obj2 = {
  sex:'男' ,
  ...obj1 ,
  weight:100
}

var obj3 = {
  ...obj1,
  weight:200,
  // 如果存在相同的属性,则后者把前者覆盖
  name:'张三'
}

console.log(obj2);
console.log(obj3);
3)参数传递
1
2
3
4
5
6
7
8
function sum(a,b,c) {
  console.log(a + b + c);
}

var arr = [1,2,3] ;

// 展开数组,依次把数据传递到函数的参数中
sum(...arr) ;

2、rest:收集

rest与spread是相对的操作,rest可以收集剩余的参数,形成可变参数的函数,与Java中的...类似。

1
2
3
4
5
6
7
8
9
10
function sum(a,...args) {
  // 分别输出参数的值
  console.log(a) ;
  console.log(args);
}

// sum(1) ;
sum(1,2,3,4)


在JS中,函数内置的数组对象(arguments),也可以收集函数的参数值。它们的区别如下:

  • rest只包含那些没有给出名称的参数,而arguments包含全部参数
  • arguments对象不是数组,它是一个像是数组的对象,而rest是数组对象
  • arguments是内置对象,默认存在于函数中,而rest必须使用...显式声明

另外,rest的参数必须定义在函数的最后一个参数中;函数对象的length属性不计算rest参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function sum(a,b,...args) {
  // 分别输出参数的值
  console.log(a);
  console.log(b);
  console.log(args);

  console.log(arguments instanceof Array) ;
  
  console.log(args instanceof Array) ;

}

sum(1,2,3,4)
// 返回1,rest不在length属性的计算范围内
console.log(sum.length);

五、解构

解构(Destructuring)是ES6新增的一个赋值方法。按归对应的位置,从数组或对象中提取值,然后赋值给变量。使用解构将极大的方便从数组或对象中取值。

1、数组解构

语法:let|var|const [变量1,…,变量N] = 数组 ;

按顺序把数组的元素赋值给变量1,变量2,…

1
2
3
4
let [a, b, c] = [100, 200, 300];
console.log(a)	// 100
console.log(b)	// 200
console.log(c)	// 300

如果变量数据与数组无数不匹配,多了忽略,少了变量赋值为undefined

1
2
3
4
5
6
7
8
9
let [a, b, c] = [100, 200];
let [aa,bb] = [10,20,30]
console.log(a)	// 100
console.log(b)	// 200
console.log(c)	// undefined


console.log(a)	// 10
console.log(b)	// 20

特殊使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 按顺序对应赋值,逗号表示跳过
let [a, , b, , c] = [100, 200, 300, 400, 500, 600];
console.log(a)	// 100
console.log(b)	// 300
console.log(c)	// 500


// 数组中的元素可以是任意类型的数据
let [aa, bb, cc, dd] = ['AA', [true, 20], { name: 'zs' }, function () { console.log('函数'); }];
console.log(aa);
console.log(bb);
console.log(cc);
dd() ;

// 结合rest使用
let [aaa,...bbb] = [1,2,3,4,5] ;
console.log(aaa);
console.log(bbb);

2、对象解构

语法:let|var|const {属性名1[:别名],…,属性名N[:别名]} = 对象 ;

按顺序把对象的属性值赋值给属性名1,属性2,…。或赋值给相应的别名变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let person = {name:'zs',age:18}

// 变量名称必须与对象的属性名称一致
let {name,age} = person ;
console.log(name);	// zs
console.log(age);		// 18

// 可以把获取的属性值赋值给指定的变量名称
let {name:xingMing,age:nianLing} = person ;
console.log(xingMing);	// zs
console.log(nianLing);	// 18

// 允许重复使用属性,允许使用表达式,可以把取出的值赋值给对象的属性
// 当不是赋值操作时,必须使用括号,转换为表达式
let obj = {} ;
({name:obj.x,age:obj['user_'+'age'],name:obj.z} = person) ;
console.log(obj);		// {x: "zs", user_age: 18, z: "zs"}

//结合rest的使用
let {username,...attrs} = {username:'小四',age:20,sex:'女'}
console.log(username);		// 小四
console.log(attrs);				// {age:20,sex:'女'}

3、解构函数参数

解构赋值也可以结合函数参数进行使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 数组解构作为参数
function sum1( [m,n] ) {
  return m + n ;
}

// 对象解构作为参数
function sum2( {m,num:n} ) {
  return m + n ;
}

// 对象解构结合默认值作为参数
function sum3({m=100},{n=300}) {
  return m + n ;
}

console.log( sum1([1,2]) );
console.log( sum2({m:10,num:20}) );

console.log(sum3({},{}));
console.log(sum3({m:300},{}));
console.log(sum3({},{n:500}));
console.log(sum3({m:500},{}));

六、箭头函数

箭头函数(Arrow Function)简化了函数的定义,它不仅是语法糖,同时也更正了this复杂不可控的情况。

1、语法

1
2
3
4
5
6
7
8
// ():代表是函数; 
// =>:必须要的符号,指向哪一个代码块;
// {}:函数体
([参数列表]) => { 函数体 } 


// 代表把一个函数赋值给fn
const fn = () => {}

2、特点

1)省略大括号

函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号

1
2
3
4
5
6
function sum(num1, num2) { 
    return num1 + num2; 
}

// ES6写法
const sum = (num1, num2) => num1 + num2 ; 
2)省略小括号

如果形参只有一个,可以省略小括号

1
2
3
4
5
6
7
function add (n) {
  return ++n ;
}

// ES6写法
// const add = (n) => ++n ;
const add = n => ++n ;
3)this关键字

箭头函数不动态绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this(父作用域)

由于箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<button>点我看看</button>

<script>
  var obj = {
    name:'测试',

    fun1 : function() {
      // 这里的this,根据调用此方法动态绑定的,由其调用的上下文決定this关键字的指向
      // 即,谁调用fun1方法,this表示的就是谁
      console.log(this);
    } ,

    fun2 : () => {
      // 箭头函数不动态绑定this,在这里,fun2函数定义的位置上下文中,当前对象指定的是window对象
      console.log(this);
    }
  }

  // this指的是obj对象
  obj.fun1() ;
  
  // this指的是window对象
  obj.fun2() ;
  
  // this指的是button对象
  document.querySelector("button").onclick = obj.fun1 ;

  // 注意:不能通过call方法的调用,改变this的指向
  // obj.fun2.call({name:'zs'}) ;
</script>
4)改变this的指向
  • 不能通过call、apply或bind调用方法,从而改变箭头方法中this的指向
  • 可以通过改变箭头函数定义上下文的this对象,从而改变箭头方法中的this指向
1
2
3
// 接上例
// this仍然是window对象
obj.fun2.call({name:'zs'}) ;

思考一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const user = { name: '张三' }

function fun() {
  // console.log(this);  

  return () => {
    // 这里的this指向的是什么对象?
    console.log(this);
  }
  
}

// 通过call调用fun方法,并重新设置this的引用(指向)
var reFun = fun.call(user) ;
reFun() ;

思考二

1
2
3
4
5
6
7
8
9
10
11
12
13
var num = 100;

var obj = {
	num : 200,
	fun : () => {
		console.log(this.num)
	}
}

// 输出的结果为?
// 箭头函数this指向的是被声明的作用域里面,而对象没有作用域的,
// 所以箭头函数虽然在对象中被定义,但是this指向的是全局作用域
obj.fun();

5)arguments、caller、callee在箭头函数中不存在

6)prototype属性在箭头函数中不存在

7)箭头函数不能作为构造器(构造方法)

8)不可以使用yield命令,因为箭头函数不能用作Generator函数。

七、循环

1、for…in

for...in语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性。

1)语法
1
2
3
for (variable in object) {
  statement
}
  • variable

    在每次迭代时,variable会被赋值为不同的属性名。

  • object

    非Symbol类型的可枚举属性被迭代的对象。

2)循环遍历数组
1
2
3
4
5
6
7
var arr = [100,200,300] ;

// 在循环遍历数组时,迭代变量指向的是数组的下标索引
for(let i in arr) {
  // console.log(i)
  console.log(arr[i])
}
3)循环遍历对象
1
2
3
4
5
6
7
8
9
10
var obj = {name:'zs',age:18,sex:'男'}

// 在循环遍历对象时,迭代变量指向的是对象的属性
for(let attr in obj) {
  // 输出属性名称:name,age,sex
  // console.log(attr)
  
  // 获取对象属性对应的值
  console.log(obj[attr])
}

说明:for ... in是为遍历对象属性而构建的,不建议与数组一起使用。

2、for…of

for...of语句可迭代对象(包括 ArrayMapSetStringTypedArrayarguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。

1)语法
1
2
3
for (variable of iterable) {
    //statements
}
  • variable

    在每次迭代中,将不同属性的值分配给变量。

  • iterable

    被迭代枚举其属性的对象。

2)迭代数组
1
2
3
4
5
6
7
8
9
10
let iterable = [10, 20, 30];

for (let value of iterable) {
    value += 1;
    console.log(value);
}

// 11
// 21
// 31
3)迭代字符串
1
2
3
4
5
6
7
let iterable = "hello";

for (let value of iterable) {
  console.log(value.toUpperCase());
}

// HELLO
4)迭代arguments对象
1
2
3
4
5
6
7
8
9
(function() {
  for (let argument of arguments) {
    console.log(argument);
  }
})(1, true, 'hello');

// 1
// true
// hello
5)迭代Map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);
// let iterable = [["a", 1], ["b", 2], ["c", 3]] ;

for (let entry of iterable) {
  console.log(entry);
}
// ["a", 1]
// ["b", 2]
// ["c", 3]


for (let [key, value] of iterable) {
  console.log(key + '=' + value);
}
// a=1
// b=2
// c=3

3、forEach

forEach() 方法对数组的每个元素执行一次给定的函数。

语法

1
arr.forEach(callback(currentValue [, index [, array]])[, thisArg])

callback为数组中每个元素执行的函数,该函数接收一至三个参数:

  • currentValue

    数组中正在处理的当前元素。

  • index 可选

    数组中正在处理的当前元素的索引。

  • array 可选

    forEach() 方法正在操作的数组。

  • thisArg 可选

    可选参数。当执行回调函数 callback 时,用作 this 的值。

1
2
3
4
5
6
7
var arr = ['你好', '我好', '大家好'];

arr.forEach(function (v,i,a) {
  console.log(v);
  console.log(i);
  console.log(a);
});

注意:forEach不能停止或退出

4、filter

过滤数组

1
2
3
4
5
6
7
8
9
10
11
12
var arr = [11, 22, 33, 44, 55, 66];

// 参数同forEach
var newArr = arr.filter(function (value, index, array) {
  // 参数一是:数组元素
  // 参数二是:数组元素的索引
  // 参数三是:当前的数组
  return value >= 50;
});

// [55,66],返回经过滤后的一个新数组
console.log(newArr);

计算购物车中,选中商品的总价

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 定义数组,判断数组各元素中的status属性是否都为 true
const arr = [
  { id:1, name:'苹果', status:true, price:10, count:1 },
  { id:2, name:'雪梨', status:false, price:20, count:2 },
  { id:3, name:'草莓', status:true, price:30, count:3 }
} ;
  
// 过滤选中的商品  
// arr.filter(item=>item.status) ;

// 方法一
// 定义累加变量
let total = 0 ;
arr.filter(item=>item.status).forEach(item=>{
  	total = total + item.price * item.count ;
}) ;
console.log(total);

// 方法二
// arr.filter(item=>item.status).reduce((累加变量,循环的当前元素)=>{},初始值);
arr.filter(item=>item.status).reduce((total,item)=>{
  	total = total + item.price * item.count ;
  	return total ;
},0);

// 简化
// arr.filter(item=>item.status).reduce((total,item)=>total = total + item.price * item.count,0);

5、some

**查找数组中是否有满足条件的元素 **

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var arr = [11, 22, 33, 44, 55, 66];

// 参数同forEach
// 查找数组中是否有满足条件的元素
// 如果不满足,则返回false
// 如果查找到满足条件的一个元素,则返回true
var bl = arr.some(function (value, index, array) {
  // 参数一是:数组元素
  // 参数二是:数组元素的索引
  // 参数三是:当前的数组
  return value >= 50;
});

// true,返回是否存在满足条件的元素
console.log(bl);

注意:区别forEach

  • forEach循环:一旦循环开始,不能终止循环
  • som循环:返回true时,终止循环

6、every

1
2
3
4
5
6
7
8
9
10
11
12
13
// 定义数组,判断数组各元素中的status属性是否都为 true
const arr = [
  { id:1, name:'苹果', status:true },
  { id:2, name:'雪梨', status:true },
  { id:3, name:'草莓', status:true }
}

const r = arr.every(function(item){
  return item.status== true;
}) ;

//const r = arr.every(item => item.status) ;
console.log(r);

八、Symbol

symbol 是一种基本数据类型 (primitive data type)。Symbol()函数会返回symbol类型的值,该类型具有静态属性和静态方法。它的静态属性会暴露几个内建的成员对象;它的静态方法会暴露全局的symbol注册,且类似于内建对象类,但作为构造函数来说它并不完整,因为它不支持语法:”new Symbol()“。

Symbol的主要目的是为了解决属性名冲突的问题,每个从Symbol()返回的symbol值都是唯一的。symbol值能作为对象属性的唯一标识,防止冲突。如果一个对象已经使用了某个属性名,再定义就会覆盖。

ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。

ES6 数据类型除了 Number 、 String 、 Boolean 、 Objec t、 null 和 undefined ,还新增了 Symbol 。

1、创建Symbol

语法

1
2
3
// 使用Symbol函数返回Symbol类型的值
// description:可选的,字符串或数字类型。对symbol的描述,可用于调试但不是访问symbol本身。
Symbol([description])

创建

1
2
3
4
5
6
var sym1 = Symbol();
var sym2 = Symbol('name');
var sym3 = Symbol(123456);

console.log(sym1) ;
console.log(typeof sym1) ;

Symbol()函数返回的值都是唯一的,哪怕描述字符串相同也是不一样的

1
2
3
4
5
const sym1 = Symbol('name') ;
const sym2 = Symbol('name') ;

console.log(sym1 == sym2) ;
console.log(sym1 === sym2) ;

使用Symbol类型数据作为对象属性名时,必须加上中括号,如[symbole]

1
2
3
4
5
6
7
8
9
10
11
const sym_name = Symbol('name') ;
const sym_age = Symbol('age') ;

var obj = {
  [sym_name] : 'zs' ,
  [sym_age] : 18
}

console.log(obj[sym_name]) ;
console.log(obj[sym_age]) ;
console.log(obj) ;

其它操作

1
2
3
4
5
6
7
8
9
10
11
12
13
var sym = Symbol('name') ;

// 输出Symbol的描述信息
console.log(sym.description);

// boolean运算,返回false
console.log(!sym);

// 转换为字符串输出
console.log(sym.toString());

// 错误,进行加法运算,无法自动转换为字符串
console.log(sym + '-');

2、全局Symbol

1)Symbol.for

Symbol.for(key) 方法会根据给定的键 key,来从运行时的 symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 创建一个全局 Symbol 
let name = Symbol.for('name') ;

// 创建一个对象,使用Symbol作为属性
let user = {
  [name] : 'tom' 
} ;

// 在全局注册表中,获取Symbol
let uname = Symbol.for('name') ;

// 输出对象的属性
console.log(user[uname]);

// 判断从全局注册中获取的Symbol类型数据是否一样
console.log(name === uname);
2)Symbol.keyFor

**Symbol.keyFor(sym) ** 方法用来获取全局symbol 注册表中与某个 symbol 关联的键。

如果全局注册表中查找到该symbol,则返回该symbol的key值,返回值为字符串类型。否则返回undefined

1
2
3
4
5
6
7
8
9
10
11
12
// 创建一个全局 Symbol 
var globalSym = Symbol.for("foo"); 
// 'foo'
Symbol.keyFor(globalSym); 
// string
Symbol.keyFor(typeof globalSym); 


// 非全部Symbol
var localSym = Symbol(); 
// undefined,
Symbol.keyFor(localSym); 

3、应用

实现枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 定义一个对象,实现枚举的作用
let TYPES = {
  HIGH : Symbol() ,
  MIDDLE : Symbol() ,
  LOW : Symbol() 
} ;

// 三个属性使用了Symbol类型数据,虽然都一样,但返回的是唯一的值
console.log(TYPES.HIGH);
console.log(TYPES.HIGH==TYPES.MIDDLE);

// 逻辑判断
var type = TYPES.HIGH ;
if(type == TYPES.HIGH) {
  console.log('高');
}

九、模板字符串

在ES6中新增的创建字符串的方式,使用反引号定义。在模板字符串,使用${变量名}的形式访问变量的值。在大括号中也支持表达式,大大提高程序的灵活性。

1
2
3
4
5
6
7
8
9
let obj = {
  name : 'zs' ,
  age : 18 ,
  sex : '男'
}

let info = `姓名:${obj.name},年龄:${obj.age + 1},性别:${obj.sex}` ;

console.log(info) ;

在模板字符串中可以调用函数

1
2
3
4
5
6
7
8
9
10
11
const sayHello = function (name) { 
  return '你好,' + name;
}; 

let info = `${sayHello('李四')}. I LOVE YOU`;

console.log(info); 


// 注意可读性
console.log(`${(function(v){return v})('hello,world')}`);

网站公告

今日签到

点亮在社区的每一天
去签到