ES6语法学习

ES6语法补充

一、let/var

  • 首先我们可以将let看成更加完美的var(因为let拥有块级作用域)
  • 注意函数也是一个作用域闭包能够解决作用域问题的原因,具体参考1.2
  • 在ES6之前因为if和for都没有块级作用域的概念,所以在很多时候,我们都必须借助于function的作用域来解决引用外面变量的问题。
  • 但在ES6中加入了let,let是有if和for的块级作用域的。

1.1 什么是作用域

变量作用域:变量在什么范围内是可用的(参考java的private,public,default,protected访问控制修饰符)

1.2 ES5没有块级作用域引起的问题

第一种场景:if

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<script>
  var func
  if(true){
    var name = 'xiong';
    func = function(){
      console.log(name)
    }
  }
  name = 'kobe'	//如果在执行下面func()之前,name的值产生了改变,那么所打印出来的name也将随之改变,这样就造成了覆盖的情况
  func()	//这样可以打印出来上面所定义的name
</script>
</body>
</html>

在这里插入图片描述

第二种场景:for

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<!--先写五个按钮,想法是点击哪一个就打印哪一个被点击的提示,但是事实是不管点击哪一个,打印出来的都是第5-->
<script>
  var btns = document.getElementsByTagName('button')
  for(var i = 1;i<btns.length;i++) {
    btns[i].addEventListener('click', function () {
      console.log('第' + (i+1) + '个按钮被点击了')
    })
  }
/*因为单击相应的那个函数可以访问到外面的i 当他访问的时候 函数内的i=0 但是他没有块级作用域 改为了外面的i 外面的i已经循环了5次,所以函数内的i也改为了5,所以,并不能做到点击那个那个的索引值被打印出来*/
</script>
</body>
</html>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7PzqV1hX-1627874981817)(C:\Users\xiong\AppData\Roaming\Typora\typora-user-images\image-20210802110313535.png)]

为了解决这种问题,在ES5中,通常采用闭包的方式(函数本身就是一个作用域)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
  var btns = document.getElementsByTagName('button')
  for(var i = 0;i<btns.length;i++) {
      /*以下就采用了闭包,也就是运行到这里需要立即执行
    函数是一个作用域,所以外面如果想改掉这个i是改不掉的 你改循环里面的i的时候 对立即执行中的i不会产生任何影响*/
    (function (i){
    btns[i].addEventListener('click', function () {
      console.log('第' + (i+1) + '个按钮被点击了')
    })
  })(i)
  }
</script>
</body>
</html>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2AGbKdk3-1627874981820)(C:\Users\xiong\AppData\Roaming\Typora\typora-user-images\image-20210802110843844.png)]

1.3 应用let解决上面的问题

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
  const btns = document.getElementsByTagName('button')
  for(let i = 0;i<btns.length;i++) {
    /*应用let之后,每个i都拥有属于自己的块级作用域,也就不是共享的i,所以i的值也就是每次循环自己使用,也就不存在不管点击那个按钮都是5的情况发生*/
      btns[i].addEventListener('click', function () {
        console.log('第' + (i+1) + '个按钮被点击了')
      })
  }
</script>
</body>
</html>

1.4 总结

let和var的作用域区别主要针对于块级作用域的拥有上面。

var不存在块级作用域,就导致了if和for存在引用外面变量时的问题,比如上述的情况,当for循环时,var定义的i由于是不存在独立的作用域,也就是每一次循环都共享了这个i的值,而i在最外层循环达到了上限值5(5个按钮的长度,btns.length),所以不管点击哪一个按钮,最终打印出来的都是第5个按钮。

当使用let之后,也就是让每一次循环都拥有了属于自己的作用域,在这个作用域中,这个i的值只属于本次循环,就不存在共享i的值导致冲突,所以就实现了点击哪一个按钮就打印点击了那一个按钮的信息。

二、const的使用

当我们修饰的标识符不会被再次赋值时,就可以使用const来保证数据的安全性。

建议:在ES6开发中,优先使用const,只有需要改变某一个标识符的时候再更改为let。

2.1 const的使用注意事项

  • 注意事项一
const a = 20;
a = 30;	// 错误使用方法:const修饰的标识符不能被修改

在这里插入图片描述

Attempt to assign to const or readonly variable(尝试分配给常量或只读变量),意思是不能给常量赋值

  • 注意事项二
const name;	//错误使用方法:const修饰的标识符必须赋值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AVsf6cNl-1627899219233)(C:\Users\xiong\AppData\Roaming\Typora\typora-user-images\image-20210802115542968.png)]

‘const’ variable without initializer is not allowed(不允许使用没有初始值设定项的“const”变量)

  • 注意事项三

常量的含义是:指向的对象不能修改,但是可以改变对象内部的属性。

const obj = {
	name: 'xiong',
	age: 20,
	height:1.87
}

obj = ;	//错误的使用方法

obj.name = 'x';	//这样才是正确方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sqpCVM4y-1627899219235)(C:\Users\xiong\AppData\Roaming\Typora\typora-user-images\image-20210802122055131.png)]

2.2 总结

const所修饰的标识符之所以不能够修改,是因为内存指向的问题,在C语言中我们称为指针,既当我们使用const name = 'kobe'时,此时的name所存放的就是name = 'kobe'的内存地址,比如说0x100,这个地址由于是const所修饰的,就固定不再能更改,所以此时的name无法再次修改。

然后当使用const修饰对象时,如:

const obj = {
	name: 'xiong',
	age: 20,
	height:1.87
}

此时obj所存放的就是后面各种属性的内存地址,比如说是0x111,这个地址是不能改变的,所以我们后面使用obj = {}是会报错的,但是如果我只是修改obj.name = 'kobe',实质上来说我没有修改0x111这个内存地址,我只是修改了这个对象内部属性的一个值,所以可以执行。

换种方式说就是,const name = 'kobe'就意味着name = 'kobe'是你的儿子,如果你想更改name,就表示你想换儿子,但是只有你自己的儿子才属于你,别人的儿子你没办法换,所以const修饰的标识符是不可修改的。

而const修饰的对象,也相当于是儿子,如下:

const obj = {
	name: 'xiong',
	age: 20,
	height:1.87
}

里面的name,age,height就相当于儿子的名字,年龄,身高,虽然说你的儿子不能更换,不能修改,但是你可以给你的儿子改名,你的儿子也会长高,年龄每年也在增长,这些属性的值都可以改变。

三、对象字面量增强写法

3.1 什么叫对象字面量

const obj = {
	name = 'xiong',
	age = 20,
	message = 'hello world'
}

如上,等号右边大括号里面的所有内容就叫做对象字面量(所修饰的内容是一个对象),一般来说,给变量赋值时,等号右边都可以认为是字面量。

字面量分为字符串字面量(string literal)、数组字面量(array literal)和对象字面量(object literal),另外还有函数字面量(function literal)。

比如:

var test = "hello world!";

const movies = ['星际穿越', '大话西游', '少年派', '盗梦空间'];

var fn = function (x) {
  alert(x)
}

其中"hello world!"就是字符串字面量,[‘星际穿越’, ‘大话西游’, ‘少年派’, ‘盗梦空间’]就是数组字面量,而函数字面量就是:

function (x) {
  alert(x)
}

3.2 属性的增强写法

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<script>
  const name = 'kobe';
  const age = 20;
  const height = 1.98;

/*  //ES5的写法:
  const obj = {
    name: name,
    age: age,
    height: height
  }*/

  /*ES6的写法: 在ES6中,如果像下面这样写,它会自动将name的变量名设置为key,name属性的值设置为value,就不用像ES5中那么繁琐的去进行name: name*/
  const obj = {
    name,
    age,
    height
  }

  console.log(obj);

</script>
</body>
</html>

3.3 函数的增强写法

//ES5的写法:
const obj = {
  run: function (){
    
  }
}

//ES6的写法:
const obj = {
  run() {
    
  }
}

如上代码可知,ES6较ES5而言,可以省略一部分内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值