vue初始与变量声明
一、什么是ECMAScript,以及es6的诞生?
1997年 ECMAScript 1.0 诞生
1999年12月 ECMAScript 3.0诞生,它 是一个巨大的成功,在业界得到了广泛的支持,它奠定了JS的基本语法,被其后版本完全继承。直到今天,我们一开始学习JS,其实就是在学3.0版的语法
2000年的ECMAScript4.0是当下ES6的前身,但由于这个版本太过激烈,对ES3做了彻底升级,所以暂时被“和谐”了
2009年12月,ECMAScript5.0版正式发布。ECMA专家组预计ECMAScript的第五个版本会在2013年中期到2018年作为主流的开发标准。2011年6月,ES5.1版发布,并且成为ISO国际标准
2013年,ES6草案冻结,不再添加新的功能,新的功能将被放到ES7中;2015年6月,ES6正式通过,成为国际标准
二、es6语法:let和const
es6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
上面代码在代码块之中,分别用let
和var
声明了两个变量。然后在代码块之外调用这两个变量,结果let
声明的变量报错,var
声明的变量返回了正确的值。这表明,let
声明的变量只在它所在的代码块有效
for循环相信大家都玩过。下面这种现象扭曲了我们块级作用域的思想!如果将var改成let就可以了!
var变量的一个例子:
变量i
是var
命令声明的,在全局范围内都有效,所以全局只有一个变量i
。每一次循环,变量i
的值都会发生改变,而循环内被赋给数组a
的函数内部的console.log(i)
,里面的i
指向的就是全局的i
。也就是说,所有数组a
的成员里面的i
,指向的都是同一个i
,导致运行时输出的是最后一轮的i
的值,也就是 10
1 var a = []; 2 for (var i = 0; i < 10; i++) { 3 a[i] = function () { 4 console.log(i); 5 }; 6 } 7 a[6]();
# 打印结果
10
let变量的一个例子:
如果使用let
,声明的变量仅在块级作用域内有效,最后输出的是 6
变量i
是let
声明的,当前的i
只在本轮循环有效,所以每一次循环的i
其实都是一个新的变量,所以最后输出的是6
。你可能会问,如果每一轮循环的变量i
都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i
时,就在上一轮循环的基础上进行计算
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6]();
# 打印结果:
6
三、不存在变量提升
var
命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined
。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。
为了纠正这种现象,let
命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
// var 的情况 console.log(foo); // 输出undefined var foo = 2; // let 的情况 console.log(bar); // 报错ReferenceError let bar = 2;
上面代码中,变量foo
用var
命令声明,会发生变量提升,即脚本开始运行时,变量foo
已经存在了,但是没有值,所以会输出undefined
。变量bar
用let
命令声明,不会发生变量提升。这表示在声明它之前,变量bar
是不存在的,这时如果用到它,就会抛出一个错误。
四、不允许重复声明
let
不允许在相同作用域内,重复声明同一个变量。
// 报错 function func() { let a = 10; var a = 1; } // 报错 function func() { let a = 10; let a = 1; }
因此,不能在函数内部重新声明参数
function func(arg) { let arg; // 报错 } function func(arg) { { let arg; // 不报错,这里{}重新定义新的私有作用域 } }
五、为什么需要块级作用域?
ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
第一种场景,内层变量可能会覆盖外层变量。
var tmp = new Date(); function f() { console.log(tmp); if (false) { var tmp = 'hello world'; } } f(); // undefined
上面代码的原意是,if
代码块的外部使用外层的tmp
变量,内部使用内层的tmp
变量。但是,函数f
执行后,输出结果为undefined
,原因在于变量提升,导致内层的tmp
变量覆盖了外层的tmp
变量。
第二种场景,用来计数的循环变量泄露为全局变量。
var s = 'hello'; for (var i = 0; i < s.length; i++) { console.log(s[i]); } console.log(i); // 5
上面代码中,变量i
只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。
六、const命令
基本语法
const
声明一个只读的常量。一旦声明,常量的值就不能改变。
const PI = 3.1415; PI // 3.1415 PI = 3; // TypeError: Assignment to constant variable.
上面代码表明改变常量的值会报错
const
声明的变量不得改变值,这意味着,const
一旦声明变量,就必须立即初始化,不能留到以后赋值
const foo; // SyntaxError: Missing initializer in const declaration
上面代码表示,对于const
来说,只声明不赋值,就会报错
const
的作用域与let
命令相同:只在声明所在的块级作用域内有效。
if (true) { const MAX = 5; } MAX // Uncaught ReferenceError: MAX is not defined
七、变量的解构赋值
数组解构赋值,就是把数组元素的值按照顺序依次赋值
解构变量就是赋值,用更少的代码来解决更多的事情
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width"> 7 <title>Title</title> 8 </head> 9 <body> 10 <script> 11 // ==============一般的操作================ 12 // let arr = [11,22,55,444]; 13 // let a = arr[0]; 14 // let b = arr[1]; 15 // let c = arr[2]; 16 // let d= arr[3]; 17 // console.log(a,b,c,d) //11 22 55 444 18 19 // ===============升级版的操作============ 20 // let[a,b,c] = [88,55,77]; //解构赋值的目的就是缩减代码,吧上面几行显示的用一行来替代 21 // console.log(a,b,c) //88 55 77 22 // 23 // let[a,b,c,[d]] = [88,55,77,100]; //会报错 24 // let[a,b,c,[d]] = [88,55,77,[100]]; //左边和右边的格式定义成一样的 25 // console.log(a,b,c,d) ; //88 55 77 100 26 // 27 // let obj={ 28 // al:"json", 29 // a2:23, 30 // a3:666 31 // }; 32 // let {aa,bb}=obj; 33 // console.log(aa,bb); //undified 34 35 36 let obj2={ 37 a5:"dddff", 38 "a4":"jggz", 39 a2:[11,22], 40 a3:666, 41 a1:'jaas' 42 }; 43 let {a1,a2,a3,a4,a5}=obj2; //注意格式是一致的,并且和里面的键对应 44 console.log(a2,a1,a3,a4,a5); //undified 45 </script> 46 </body> 47 </html>
八、数组的扩展
1、判断数组当中是否存在某个数值 console.log(arr.indexOf(1000)) console.log(arr.includes(201)) 2、对数组的遍历 forEach():范围比map广,他能做的事情map不一定能做 map():map能做的事情forEach一定能做 arr.forEach(function (value,index) { console.log(value); }) //也可以不用map,在forEach里面就能做操作,为了简单用一个map也可以解决,具体见示例 var arr2 = arr.map(function (value,index) { return value+1 }) 3)对数组的过滤 var arr4 = arr.filter(function (value,index) { return value > 50 }) console.log(arr4);
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width"> 7 <title>Title</title> 8 <script> 9 // var arr=[77,88,99,44]; 10 // //如果对数组进行循环,用for循环 11 // var arr2=[]; 12 // for (var i=0;i<arr.length;i++){ 13 // arr2.push(arr[i]+1); 14 // } 15 // console.log(arr2); 16 17 // =============================== 18 // var arr=[77,88,99,44]; 19 // //在es6中的循环如下,对里面的元素都加1 20 // arr.forEach(function (value,index,arr) { 21 // console.log(value);// 77 88 99 44 22 // console.log(index); //0 1 2 3 23 // }); 24 // var arr2=arr.map(function (value,index) { //map是一个循环生成一个新的数组 25 // return value+1 26 // }); 27 // console.log(arr2);//78 89 100 45 28 29 30 // //查询一下90在不在arr里面,一般可用于判断 31 // var arr2=[11,22,33,44]; 32 // console.log(arr2.indexOf(44)); //3 根据值取索引,如果有就显示索引,没有就显示-1 33 // console.log(arr2.indexOf(1000)) ; //-1 根据值取索引,如果有就显示索引,没有就显示-1 34 // 35 // console.log(arr2.includes(33)) ; // true 看包含不包含,如果包含返回true,不包含返回false 36 37 //============================================== 38 // let arr3=[11,22,33]; 39 // for (var i in arr3){ 40 // console.log(i) ; //打印的是索引 41 // console.log(arr3[i]); //打印值 42 // } 43 // for (var j of arr3) { 44 // console.log(j); //打印的是值 45 // } 46 47 // 过滤 ===================================== 48 arr = [51,2,14,845]; 49 // var arr4 = arr.filter(function (value,index){ 50 // console.log(value); 51 // if (value>50){ 52 // return value //[51, 845] 53 // } 54 // }); 55 // console.log(arr4) 56 57 var arr4 = arr.filter(function (value,index) { 58 return value>50 //和map一样,一定要有个返回值 59 }) 60 console.log(arr4) 61 </script> 62 </head> 63 <body> 64 65 </body> 66 </html>