let const
- let&const介绍
let:声明变量,类似于var,但let所声明的变量只在let命令所在的代码块内有效
{
let a = 1;
var b = 2;
}
a // not defined
b // 2
const声明一个只读的常量,这个常量的值不可改变
const version = 1.02;
version // 1.02
version = 2.0 // error
- let&const 不允许重复声明
let不允许在相同作用域内重复声明
let a = 1;
let a = 2; // error
const一样不可重复声明
var c = 1
let d = 2
const c // error
const d // error
- let&const 不存在变量提升
var变量提升
console.log(a) // undefined
var a = 1
--------可以写成---------
var a;
console.log(a) // undefined
a = 1
而let和const不存在变量提升
console.log(a) // not defined
console.log(b) // not defined
let a = 1
const b = 2
- 块级作用域
{{{{{let insane = 'Hello World'}}}}};
// 块级作用域的任意嵌套
外层作用域无法读取内层作用域的变量。内层作用域可以定义外层作用域的同名变量。
{
let a = 1
{
a++
console.log(a) // 2
}
}
块级作用域的出现,实际上使得获得广泛应用的立即执行匿名函数(IIFE)不再必要了。
// IIFE写法
(function () {
var tmp = ...;
...
}());
// 块级作用域写法
{
let tmp = ...;
...
}
因为函数本身的作用域,在其所在的块级作用域之内声明函数应该写成函数表达式,而不是函数声明语句。 。
// 函数声明语句 不推荐
{
let a = 'secret'
function f() {
return a
}
}
// 函数表达式 推荐
{
let a = 'secret'
let f = function () {
return a
}
}
- let基本应用
在for循环中使用
for(let i = 0; i < 10; i++){}
cosole.log(i) // not defined
-------------避免变量值在作用域块外被使用--------------
for(var i = 0; i < 10; i++){}
cosole.log(i) // 10
- const基本应用
const version = 1.1
version = 2.0 // error
// 设置常量不可改变
字符串模板
字符串for...of
ES6为字符串添加了迭代器接口(Iterator), 使得字符串可以被for...of遍历
let str = 'hello world!'
for (let s of str) {
console.log(s)
}
includes(), startsWidth(), endsWith()
includes():返回布尔值,表示是否找到了参数字符串。 startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
var str = 'Hello world!';
str.startsWith('Hello') // true
str.endsWith('!') // true
str.includes('o') // true
这三个方法都支持第二个参数,表示开始搜索的位置。
var str = 'Hello world!';
str.startsWith('world', 6) // true
str.endsWith('Hello', 5) // true 表示前5位有没有字符串
str.includes('Hello', 6) // false 从第6位置开始搜索
使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。
repeat()
repeat方法返回一个新字符串,表示将原字符串重复n次。
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
模板字符串
// ES6之前的字符串拼接
var str = "There are <b>" + basket.count + "</b> " +
"items in your basket, " +
"<em>" + basket.onSale +
"</em> are on sale!"
// ES6的字符串拼接
let str = `There are <b>${basket.count}</b> items
in your basket, <em>${basket.onSale}</em>
are on sale!`
模板字符串使用反引号 ` 表示多行字符串,所有的空格和缩进都会被保留在输出之中
模板字符串中嵌入变量,需要将变量名写在${}之中。
function authorize(user, action) {
if (!user.hasPrivilege(action)) {
throw new Error(
// 传统写法为
// 'User '
// + user.name
// + ' is not authorized to do '
// + action
// + '.'
`User ${user.name} is not authorized to do ${action}.`);
}
}
大括号内部可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。
var x = 1;
var y = 2;
`${x} + ${y} = ${x + y}`
// "1 + 2 = 3"
---------------------------
var obj = {x: 1, y: 2};
`${obj.x + obj.y}`
// 3
箭头函数
基本用法
let f = v => v
------等价于------
let f = function(v) { return v }
如果箭头函数不需要参数或需要多个参数,需要使用一个圆括号代码参数部分
var f = () => 5;
// 等同于
var f = function (){ return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。
var sum = (num1, num2) => { return num1 + num2; }
由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号。
var getTempItem = id => ({ id: id, name: "Temp" });
注意点
箭头函数有几个使用注意点。
1函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
2不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
3不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
4不可以使用yield命令,因此箭头函数不能用作Generator函数。
上面四点中,第一点尤其值得注意。this对象的指向是可变的,但是在箭头函数中,它是固定的。
function foo() {
setTimeout( () => {
console.log("id:", this.id);
},100);
}
foo.call( { id: 42 } );
// id: 42
function f(){
setTimeout(function(){
console.log('id', this.id)
},100)
}
f.call({id: 42})
// id undefined
上面代码中,setTimeout的参数是一个箭头函数,100毫秒后执行。如果是普通函数,执行时this应该指向全局对象,但是箭头函数导致this总是指向函数所在的对象
Class
- 构造函数
ES6前构造函数和公用方法的写法
function Person(name, age){
this.name = name
this.age = age
}
Person.prototype.showName = function(){
return this.name
}
Person.prototype.showAge = function(){
return this.age
}
var p = new Person('boy', 10)
ES6语法下的新写法
class:类
constructor:构造函数,生成实例后自动执行
class Person {
constructor(name = 'name', age = 0) {
this.name = name
this.age = age
}
showName() {
return this.name
}
showAge() {
return this.age
}
}
let p = new Person('man', 20)
- 继承
ES6之前的继承
function People(name, age) {
Person.apply(this, arguments)
}
People.prototype = new Person()
var p = new People('tom', 22)
ES6语法的继承extends
class People extends Person {
}
let p = new People('tom', 22)
ES6语法下继承写私有内容
class People extends Person {
constructor(name, age, job = 'work') {
super(name, age)
this.job
}
showJob() {
return this.job
}
}
let p = new People('tom', 22, 'fontend')
用super()把所继承父类的参数导入
Module
export命令
export 命令用于规定模块的对外接口
// exp.js
export let name = 'tom';
export let age = '15';
export let year = 2000;
export let obj = {a: 1, b:2}
等价于
// exp.js
let name = 'tom';
let age = '15';
let year = 2000;
let obj = {a: 1, b:2}
export {name, age, year, obj}
优先第二种写法
import命令
使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块(文件)
// main.js 我们导入上面的exp.js文件
import {name, age, year, obj} from './exp.js'
console.log(name, age, year, obj)
网友评论