Es6(1)---let,const,解析赋值,正则扩展

1,let,const:

let:

if(true){
	let a=12;
 }
 console.log(a);//error

有上述栗子可以看出来,大括号内是一个独立的作用域,由此es6中提出了块级作用域;
什么是块级作用域:

 {
 	//块级作用域
 }
 if(){}
 for(){}
 while(){}

let与var区别:
1>

var a=12;
function fn(){
	var a=5;
	console.log(a);//5
}
fn();

var a=12;
    function fn2(){
    	console.log(a);//undefined
    	var a=5;
    }
    fn2();

用var在函数中的操作之后声明变量,相当于对函数内定义的变量提升了,就是进行了预解析。

	let a=12;
     function fn(){
        	let a=5;
        	console.log(a);//5
        }
        fn();

    	var let=12;
        function fn2(){
        	console.log(a);//error  TDZ 开始  暂时性死区
        	var let=5;//TDZ 结束
        }
        fn2();

而用let定义的变量,没有预解析,不存在变量提升。
在代码块内,只要是let定义的变量。在定义之前使用都会报错,必须先定义在使用。
2>

var a=12;
 var a=5;
 console.log(a);//5

用var定义的变量可以重复定义,程序会正常运行,后面定义的会覆盖前面的。

let a=12;
let a=5;
console.log(a);//error

用let定义的变量不能重复定义,
3> 在同级作用域不能重复定义。

for(var i=0;i<3;i++){
	//todo
}
console.log(i);//3

在for循环中用var定义的变量,在循环外也可以用,

for(let i=0;i<3;i++){
	//todo
}
console.log(i);//error

用let只能在for内使用

for(let i=0;i<3;i++){
		let i='abc';
    	console.log(i);//abc  abc abc
    }

在for循环中,有两个作用域,小括号是父级作用域,而花括号是子级作用域
在同级作用域不能重复定义。

下面给大家说一个我们经常会遇到的问题:

    for (var i=1; i<=9; i++) {
   			setTimeout( function timer(){
  			console.log( i );
 		  },1000 );
 	}

上面的代码,由于setTimeout是异步的,那么在真正的1000ms结束前,其实10次循环都已经结束了,最终只会输出10。
我们有两种解决方法:

第一种就是let方法:

for (let i=1; i<=9; i++) {
   setTimeout( function timer(){
        console.log( i );
    }, 1000 );

}

还有另外一种方法,改成

for (var i=1; i<=9; i++) {
    (function(j){
      setTimeout( function timer(){
           console.log( j );
      	}, 1000 );
  	 })( i );
 }

这两种方法都是通过解决变量作用域的问题来实现的
let声明的变量仅在块级作用域有效,所以这里的i只在本轮循环有效果,每次循环的i其实都是一个新的变量 中。

const:

定义常量,在定义是必须有值,那就是不可修改的。
但是特殊的,当它定义的是对象类型时,对象内的属性值可以改变。因为对象是引用类型,返回的时对象的地址,而const定义的常量名称接受的也是对象的地址,对象内部属性可以改变,地址不能变。(freeze)

2.解析赋值:

(数组、对象、字符串、布尔值、函数参数、数值)

数组:

例:

let a,b;
[a,b]=[1,2];
console.log(a,b);//1,2

let a,b;
[a,...b]=[1,2,3,4,5,6];
console.log(a,b);//1,数组[2,3,4,5,6]

let a,b;
[a,,...b]=[1,2,3,4,5,6];
console.log(a,b);//1,数组[3,4,5,6]

其中,,之间占位;

let a,b;
[a,b=3]=[1];
console.log(a,b);//1,3

给变量设置默认值,使没有在结构上形成配对的变量也有值,不然最后变量输出为undefined。

对象

let o={
p:42,
q:true
}
let {p,q}=o;
console.log(p,q);//42,true

特别重要的,应用于前后端通信,json格式:

let metaData={
	title:'abc',
	test:[
	title:'test',
	desc:'description'
	]
}
let{title:esTitle,test:[{title:cnTitle}]}=metaData;
console.log(esTitle,cnTitle);

3.正则:

在 ES5 中,RegExp构造函数的参数有两种情况。

第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag)。

var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;

第二种情况是,参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝。

var regex = new RegExp(/xyz/i);
// 等价于
var regex = /xyz/i;

RegExp构造函数的参数是一个正则表达式的时候,ES5 不允许此时使用第二个参数添加修饰符,否则会报错。

var regex = new RegExp(/xyz/, 'i');
// Uncaught TypeError: Cannot supply flags when constructing one RegExp from another

在es6中有两个参数,允许第一个参数是正则表达式,同时允许第二个参数再去填写修饰符,而第二个参数的修饰符会覆盖第一个正则表达式所用的修饰符。

new RegExp(/abc/ig, 'i').flags
// "i"

flags:es6新增的用来获取正则对象修饰符的属性。

y修饰符:

var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;

r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]

r1.exec(s) // ["aa"]
r2.exec(s) // null

y修饰符与es5中的g修饰符都是全局匹配,但是也有不同之处,g修饰符是从上次匹配的位置继续寻找,直到找到匹配的位置,而y修饰符则需要第一个字符就要匹配成功。

u修饰符:

在处理的字符串中有大于2个字节的字符加u,es5中的.修饰符的定义为可匹配所有字符,在es6中修改了这其中的bug,.修饰符不能匹配大于2字符长度的字符。

s修饰符:dotAll 模式

正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是行终止符除外。

以下四个字符属于”行终止符“。
U+000A 换行符(\n)
U+000D 回车符(\r)
U+2028 行分隔符(line separator)
U+2029 段分隔符(paragraph separator)

/foo.bar/.test('foo\nbar')
// false

但是,很多时候我们希望匹配的是任意单个字符,这时有一种变通的写法。

/foo[^]bar/.test('foo\nbar')
// true

这种解决方案毕竟不太符合直觉,所以现在有一个提案,引入/s修饰符,使得.可以匹配任意单个字符。

/foo.bar/s.test('foo\nbar') // true

这被称为dotAll模式,即点(dot)代表一切字符。所以,正则表达式还引入了一个dotAll属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。

const re = /foo.bar/s;
// 另一种写法
// const re = new RegExp('foo.bar', 's');

re.test('foo\nbar') // true
re.dotAll // true
re.flags // 's'

/s修饰符和多行修饰符/m不冲突,两者一起使用的情况下,.匹配所有字符,而^和$匹配每一行的行首和行尾。

猜你喜欢

转载自blog.csdn.net/liveingcc/article/details/86603499