第二章 ECMAScript 和 TypeScript概叙

  • A+
所属分类:Web前端
摘要

在Es6中引入其他声明变量的方法,那便是let和const,那么为什么要添加新的声明方式呢???让我们看看几段代码


var / let / const声明变量

在Es6中引入其他声明变量的方法,那便是letconst,那么为什么要添加新的声明方式呢???让我们看看几段代码

var a = 1; // ~~~ var a = 2; console.log(a); 

上面的代码是可以完美运行的,而且我们的第一个a变量还会被第二个声明的a覆盖,所以我们打印出来的就是2,假如中间写了很多代码,而且命名不规范的情况下,这里可能会有产生很多bug,听说以前很多问题就是有这个的身影.

let 使用
let a = 1; // ~~~ let a = 2;     //这里就会报错 console.log(a); 

你会发现,在第二个let a的时候就报错了,运行也会有报错

var x = 'global'; let y = 'global'; console.log(this.x); // "global" console.log(this.y); // undefined 

var 申明的变量会绑定到全局变量上,至少是当前对象上,而let不会

function varTest() {   var x = 1;   {     var x = 2;  // 同样的变量!     console.log(x);  // 2   }   console.log(x);  // 2 }  function letTest() {   let x = 1;   {     let x = 2;  // 不同的变量     console.log(x);  // 2   }   console.log(x);  // 1 } 

let声明的变量只在其声明的块或子块中可用,这一点,与var相似。二者之间最主要的区别在于var声明的变量的作用域是整个封闭函数。注意:这里是用{}围成的子块,以下情况是一样的打印结果

function varTest() {       var x = 1;       function test() {             var x = 2; // 不同的变量             console.log(x); // 2       }       test();       console.log(x); // 1 } function letTest() {       let x = 1;       function test() {             let x = 2; // 不同的变量             console.log(x); // 2       }       test();       console.log(x); // 1 } 

console.log(name); console.log(age); var name = "测试"; let age = 18; 

运行结果

第二章 ECMAScript 和 TypeScript概叙

变量提升: 可以看到,name打印出来是undefined,而age直接报错,可见var声明的变量有变量提升的,let却没有
暂时性死区:ES6 明确规定,如果区块中存在 let 和 const 命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。只要在声明之前使用这些变量,就会报错。这种语法称为“暂时性死区”(temporal dead zone,简称TDZ)。

const使用

const声明的为常量,只读,不可修.(不可修的仅仅是引用地址不可以变而已,但是引用地址内部变化是可以的),怎么理解呢!!!

const a = 0; const b = {     c: 0,     d: 1 } b.c = 15;   // 没有问题 b = 14;     // 抛出异常 a = 12;     // 抛出异常  

运行结果

第二章 ECMAScript 和 TypeScript概叙

更多资料MDN

模板字面量

说实话,第一眼看到这个的时候,我就喜欢上了它,真的太方便了,以后都不用拼接字符串了

键盘位置

在键盘的Esc下的第一个按键

使用
  let message = "什么玩意";   let logMessage = `     模板字面量是${message},     我是第二行了吧   `;   console.log(logMessage) // 模板字面量是什么玩意 

${}代表里面放的是变量,而且这里面的空格什么的都会保留

运行结果

第二章 ECMAScript 和 TypeScript概叙

箭头函数

听说JavaScript开发中有几大公认的难点,如果上面提到的var声明变量混淆算是一个小难点,那么this指向就是一个大boss,这个问题一直存在现代编程中,但是箭头函数的出现,解决了绝大多数的this指向问题

this指向保持不变
 // 图片地址  let img_url = "https://upload-images.jianshu.io/upload_images/13962818-8ab62dc051112573.jpg?imageMogr2/auto-orient/strip|imageView2/2/w/500/format/webp";  // 创建对象  let img = new Image();  // 改变图片的src  img.src = img_url;  // 加载完成执行  img.onload = function () {    // 打印    console.dir(this);  };   // 创建对象  let img1 = new Image();  // 改变图片的src  img1.src = img_url;  // 加载完成执行  img1.onload = () => {       // 打印       console.log(this);  }; 

运行结果

第二章 ECMAScript 和 TypeScript概叙

使用箭头函数的时候,this还是指向外部的window对象,而普通函数的this指向调用者(这里的调用者是img对象)

如果只有一条语句,可以省掉return
let arr = [1, 2, 3, 4, 5, 6, 7]; let filterArr = arr.filter((item) => item % 2 === 0); console.log(arr, filterArr); 

运行结果

第二章 ECMAScript 和 TypeScript概叙

这里的filter方法需要返回一个值,如果返回值是true,就保留这个值,如果是false就过滤掉,会返回一个新数组,原数组不变,但是我们看到这个箭头函数好像没有返回一样,这就是箭头函数的第二个特性,如果只有一条语句,可以省略return

函数的参数默认值

function sum(x = 1, y = 2, z = 3){     return x + y + z; } sum();      // 6 sum(2 , 3); // 8 

声明展开和剩余参数

let params = [1,2,3]; console.log(...params); 

运行结果

第二章 ECMAScript 和 TypeScript概叙

有时候我们会想要编写一个动态参数的方法,这个时候就可以使用这个符号
 function push(targetArr, ...nums){     for(let i = 0,len = nums.length; i < len; i++){         targetArr.push(nums[0]);     } }  let arr = []; push(arr, 12, 45); console.log(arr) 

运行结果

第二章 ECMAScript 和 TypeScript概叙

我这样的一个push方法就支持一个或者多个参数,而不需要把后面的参数整合成对象,或者数组,我只是觉得这样写更舒服点

乘方运算符

// Es5 const area = 3.14 * Math.pow(r, 2); // Es6 const area = 3.14 * (r ** r); 

模块

注意:这里面如果你想用HTML来测试模块的内容,需要做两步

  • script标签上记得加上type="module",不加报错不能在模块外部使用import语句
  • 使用服务器模式打开HTML文件(vscode可以安装一个Live Server插件,ws可以直接点击右上角选择浏览器运行),不这样报错跨域
index.js
// 1  export const index = 5555;  const key = "key"; const good = 1234;  // 2 A export {       key,good }  // B export default {       test :function(params) {           console.log(params)         } }  
测试html
<script type="module">             import { index } from "./index.js";    //导入1             import utils from "./index.js";        //导入2             import * as newUtils from "./index.js";//导入3             console.log(index);             console.log(newGood);             console.log(newKey);             utils.test("这个世界");             console.log(newUtils);             console.log(newUtils.index);             console.log(newUtils.good);             console.log(newUtils.key);             newUtils.default.test("这个世界");  </script> 

12两种其实是一种,只是1是一个个的导出,而2是一次导出多个,两种方式随便那个都可以.我的建议是,如果导出的东西不多,可以用2,当导出的内容过多了,这个时候导出语句可能在很下面,所以推荐一个一个的导出(个人想法而已)

后面两种A(export) 和 B(export default)导出有以下几点注意

  1. export导出的元素,可以使用import {A, B} from "文件地址"引入,这里相当于做了一个结构赋值,并且相当于指定了一个对象
  2. export default导出的元素可直接接收,默认导出的是个匿名对象,然后需要指定该对象的名字,才可以使用其属性,这里不能结构导出
  3. 第三个导入,直接将内部所有的导出都集中到newUtils,打印出来后,你会发现导出B中的对象放在了newUtilsdefault属性中了

运行结果

第二章 ECMAScript 和 TypeScript概叙

改变导出的名称
index.js
const index = 5555; const newInfo = 4444; const key = "key"; const good = 1234;   export {       newInfo,       index as newIndex } export default {       newKey :key,       good,       test :function(params) {           console.log(params)         } } 
<script type="module">             import { newIndex, newInfo as info } from "./index.js";             import utils from "./index.js";             import * as newUtils from "./index.js";             console.log(newIndex);         //关注点1              console.log(info);             //关注点2             utils.test("这个世界");             console.log(utils.good);             console.log(utils.newKey);             console.log(newUtils);              console.log(newUtils.newInfo);  //关注点3             console.log(newUtils.newIndex); //关注点4             newUtils.default.test("这个世界");  </script> 

运行结果

第二章 ECMAScript 和 TypeScript概叙

改名方式1

good , key都通过 export default导出,但是key却变了一个名称newKey,这导致导入使用的时候需要使用新的键newKey

改名方式 --- as
  • newInfo , index都通过 export导出,但是index却变了通过as转为newIndex,这导致导入使用的时候需要使用新的键newIndex
  • newInfo 导出的时候为 newInfo,但是我们可以在导入使用的时候使用as关键字,将newInfo 改名为 info

最后还要关注一下newUtils这个对象,是不是发现在导出前改名的直接反应在这里,但是通过导入时改名并没有体现出来,当然这也是在意料之中的事了