var
- 可以重复声明
var a = 12;
var a = "this is a"; //重复声明了a
console.log(a); //输出this is a
- 存在变量提升
console.log(b); //变量提升,var b 被提升至所在作用域顶部,输出undefined
var b = "this is b";
- 无法限制修改
var c = "this is c";
c = "this is cc";
c = "this is ccc";
console.log(c); //输出this is ccc
- 没有块级作用域
{
var d = "this is d";
console.log(d); //输出this is d
}
console.log(d); //输出this is d
let
- 作用
//声明变量
let a;
let b, c, d;
let e = 100;
let f = '521', g = 'i am', h = []
- 不能重复声明
let star = '罗志祥'
let star = '小猪'
//这里会报错:Uncaught SyntaxError: Identifier 'star' has already been declared
- 没有变量提升
console.log(music)
let music = "精舞门";
//这里会报错:Uncaught ReferenceError: music is not defined
- 3.有块级作用域
{
let girl = '周扬青';
console.log(girl); //输出 周扬青
}
console.log(girl);
//这里会报错:Uncaught ReferenceError: girl is not defined
- 4.不影响作用域链
{
let name = 'hello ES6';
function say(){
console.log(name)
}
say()
}
const
//声明常量 -值不能修改的量称之为常量
const URL = 'https://www.jianshu.com/u/097952b889b8'
- const包含let的所有特性, 区别是声明的变量不可以修改( const只是保证变量名指向的地址不变,并不保证该地址的数据不变,简单的说就是只能保证一直指向的是某一个地址,而无法保证这个地址里面的值是否改变,这种情况通常出现在声明的是一个数组或者对象)
- 1.一定要赋初始值
const a;
//这里报错:Uncaught SyntaxError: Missing initializer in const declaration
- 一般常量使用大写
const URL = 'https://www.jianshu.com/u/097952b889b8'
- 3.常量的值不能修改
const URL = 'https://www.jianshu.com/u/097952b889b8'
console.log(URL)
URL = 'baidu.com'
- 对于数组和对象的元素修改, 不算作对常量的修改, 不会报错。因为常量所指向的地址没有发生改变, 变化的事数组元素
const TEAM = ['UZI', 'MLXG', 'MING']
TEAM.push('张三')
console.log(TEAM) // ["UZI", "MLXG", "MING", "张三"]
<body>
<h1>一个小例子,带你看差别</h1>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<script>
var allbtn = document.getElementsByTagName('button');
// 加了一层函数,原来的var只有function才能限制作用域
// for(var i = 0;i<allbtn.length;i++){
// (function(i){
// allbtn[i].onclick=function(){
// alert(i)
// }
// })(i)
// }
//es6方法 直接用块级定义变量let
for (let i = 0; i < allbtn.length; i++) {
allbtn[i].onclick = function () {
alert(i)
}
}
</script>
</body>
箭头函数
- 1.如果只有一个参数,()可以省略
- 2.如果只有一个return,{}可以省略
例:
let f = v => v*2;
console.log(f(12))
等同于
let f = function (v) {
return v*2;
};
console.log(f(12))
- 箭头函数有几个使用注意点。
(1)函数体内的this对象, 就是定义时所在的对象, 而不是使用时所在的对象。
var obj = {
age: 1,
say: function () {
setTimeout(function () {
console.log(this, this.age); // window ,undefined
}, 0);
},
}
obj.say()
var obj = {
age: 1,
say: function () {
setTimeout(() => {
console.log(this, this.age); // obj 1
}, 0);
}
}
obj.say()
这里可以看出箭头函数中访问的this实际上是其父级作用域中的this,箭头函数本身的this是不存在的,这样就相当于箭头函数的this是在声明的时候就确定了(因为相当于作用域嘛),这个特性是很有用的
(2)不可以当作构造函数, 也就是说, 不可以使用new命令, 否则会抛出一个错误。
var Person = (name) => { // Uncaught TypeError: Person is not a constructor
this.name = name;
}
var person = new Person('Jack');
这个特性很容易测试,如果上一条明白的话也很容易理解: 箭头函数压根就没有this,当然不能作为构造函数(如果明白构造函数new的过程的话,插一句: new的过程其实就是创建一个对象,将this指向该对象,然后执行代码初始化这个对象,最后返回)
(3)不可以使用arguments对象, 该对象在函数体内不存在。 如果要用, 可以用 rest 参数代替。
let foo = (val) => {
console.log(arguments); // Uncaught ReferenceError: arguments is not defined
};
foo();
这个特性也很好测试, 但是实在要使用arguments对象要怎么办呢? 我们可以使用es6的另一个新特性rest参数, 完美替代
var foo = (...args) => {
console.log(args); // [1, 2, 3]
};
foo(1, 2, 3);
(4)不可以使用yield命令, 因此箭头函数不能用作 Generator 函数。
上面四点中, 第一点尤其值得注意。 this对象的指向是可变的, 但是在箭头函数中, 它是固定的。
//小例子
let arr = [56, 1, 66, 6, 8, 13, 43]
arr.sort((n1, n2) => {
return n1 - n2 //从小到大排序,如果改成return n2-n1 就是从大到小
})
console.log(arr)
- 一.参数扩展/数组展开
// 参数扩展:
function show(a, b, ...args) {
console.log(a) //第一个参数 1
console.log(b) //第二个参数 2
console.log(args) //剩余的参数[4,45,56,333],相当于把剩余的参数收集起来
}
show(1, 2, 33, 45, 91, 666)
//数组展开:
let arr = [1, 2, 'abc', '99', {name: '张三'}]
console.log(...arr) //相当于把数组里面的内容掏出来直接显示
- 二.默认参数(你传了就显示你的,你不传就显示我默认的)
function defaulNum(num1, num2 = 2, num3 = 'abc') {
console.log(num1) //undefined
console.log(num2) //2
console.log(num3) //'abc'
}
defaulNum()
数组循环
- 1.forEach 循环(遍历,没有返回值)
let arr = [1, 3, 5, 7, 9]
arr.forEach((item, index, arr) => {
console.log(item,index,arr)
})
- 2.map 映射(返回一个新的数组,可以在里面做一些操作,例如更改数据和整理数据结构)
let arr = [
{title:'node.js',read:100,hot:true},
{title:'react',read:1,hot:true},
{title:'vue',read:12,hot:true},
{title:'angular',read:78,hot:true},
]
//2.1更改数据
//let newarr = arr.map((item, index, arr) => {
// console.log(item, index, arr)
// item.hot = false
// return item
//})
//2.2整理数据
let newarr = arr.map((item, index, arr) => {
let json = {}
json.i = `^ _ ^${item.title}`
json.in = item.read + 100
json.hot = item.hot == true && '热门框架'
return json
})
console.log(newarr)
- 3.filter 过滤(过滤数组,包含满足条件的数组项,返回一个新数组)
let arr = [1, 3, 5, 7, 9]
let newarr = arr.filter((item, index) => {
if (item > 5) {
return true
}
})
console.log(newarr) // 7 9
// 例:要删除列表中的某一行,可以根据点击删除按钮传递的id来过滤到这个元素,并且删除。
del= (id) => {
const { dataList } = this.state;
const newDataList = dataList .filter((item, index) => {
return item.id !== id;
});
this.setState({
dataList : newDataList ,
});
};
// 去重小例子
let newarr;
let arr = ['a', 'ab', 'ab', 'c', 1, 1, 2];
newarr = arr.filter(function (item, index, arr) {
return arr.indexOf(item) === index;
});
console.log(newarr)
- some 类似查找(数据里某一个元素复合条件,就返回true)
every 类似查找(数据里所有元素复合条件,就返回true)
- some 类似查找(数据里某一个元素复合条件,就返回true)
let arr = ['banana','apple','pear']
// let res = arr.some((item,index,arr)=>{
// return item == 'apple'
// })
let res = arr.every((item,index,arr)=>{
return item == 'banana','apple','pear'
})
console.log(res)
字符串模板
let name = '张三'
let age = 18;
console.log(`我叫${name},今年${age}岁!`)
- 方法
startsWith
判断字符串是不是以https://开头的,是则返回true,反之false
let str = 'https://www.jianshu.com/u/097952b889b8'
console.log(str.startsWith('https://'))
endsWith
判断字符串是不是以jpg结尾,是则返回true,反之false
let img = 'item.jpg'
console.log(str.endsWith('.jpeg'))
padStart
往前面填充内容 参数1:整个字符串的长度,参数2:填充的内容
let num = '1'
console.log(num.padStart(num.length+1,'0'))
padEnd
往后面填充内容
let sid = '0313'
console.log(sid.padEnd(5,'-'))
对象简洁语法
现在框架中都采用的这种语法,优化代码,推荐使用
let name = 'curry'
let age = 31;
let json = {
name, //name:name
age, //age:age
show(){
return this.name
}
}
console.log(json.show())
Object.is()
方法用于确定两个值是否相等。它类似于===运算符,但Object.is()方法有一些特殊情况和使用“===”的结果是不一致的,例:
console.log(Object.is(0, -0)); //false
console.log(0 === -0); //true
console.log(Object.is(NaN, 0 / 0)); //true
console.log(NaN === 0 / 0); //false
console.log(Object.is(NaN, NaN)); //true
console.log(NaN === NaN); //false
Object.assign
方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)
let json1 = {a:1}
let json2 = {b:2}
let json3 = {c:3}
let obj = Object.assign({},json1,json2,json3)
console.log(obj) //{a: 1, b: 2, c: 3}
Object.values()
Object.keys()
Object.entries()
遍历
let json = {name:'张三',age:18, add:'北京'}
console.log(Object.values(json)) //取到的是value
console.log(Object.keys(json)) //取到的是key
console.log(Object.entries(json))
Promise
let num = 1;
let promise = new Promise((resolve, reject) => {
/* resolve 代表成功 reject 代表失败 */
if (num >= 10) {
resolve('成功了')
} else {
reject('失败鸟')
}
})
promise.then(res => {
console.log(res) //成功了
}).catch(err => {
console.log(err) //失败鸟
})
-
Promise.all()
把promise打包,扔到一个数组里面,打包完还是一个promise对象- 注意:必须确保all里面的状态都是成功(resolve)的
let p1 = Promise.resolve('success1')
let p2 = Promise.resolve('success2')
let p3 = Promise.resolve('success3')
const p = Promise.all([p1, p2, p3]);
p.then(res => {
console.log(res) //["success1", "success2", "success3"]
})
Generator
先看下面的Generator函数,
function* helloGenerator() {
console.log("this is generator");
}
这个函数与普通的函数区别是在定义的时候有个*,我们来执行下这个函数。
function* helloGenerator() {
console.log("this is generator");
}
helloGenerator(); //没有执行
我们发现,并没有像普通的函数一样,输出打印日志。我们把代码改成下面:
function* helloGenerator() {
console.log("this is generator");
}
var h = helloGenerator();
h.next();
这个时候如期的打印了日志,我们分析下,对于Generator函数,下面的语句
var h = helloGenerator();
仅仅是创建了这个函数的句柄,并没有实际执行,需要进一步调用next()
,才能触发方法。
function* helloGenerator() {
yield "hello";
yield "generator";
return;
}
var h = helloGenerator();
console.log(h.next());//{ value: 'hello', done: false }
console.log(h.next());//{ value: 'generator', done: false }
console.log(h.next());//{ value: 'undefined', done: true }
这个例子中我们引入了yield这个关键字,分析下这个执行过程
1.创建了h对象,指向helloGenerator的句柄,
2.第一次调用nex()
,执行到 "yield hello" ,暂缓执行,并返回了 "hello"
3.第二次调用next()
,继续上一次的执行,执行到 "yield generator" ,暂缓执行,并返回了 "generator" 。
4.第三次调用next()
,直接执行 return ,并返回 done:true ,表明结束。
经过上面的分析,yield
实际就是暂缓执行的标示,每执行一次next()
,相当于指针移动到下一个yield
位置。
总结一下,Generator函数是ES6提供的一种异步编程解决方案。通过yield
标识位和next()
方法调用,实现函数的分段执行
网友评论