1.let
和var
(面试题)
let
声明局部变量,只在当前代码块内有效,并且不能提前声明
一、
二、
console.log(i);//i is not defined
let i=0;
三、
{
let a = [];
for (let i = 0; i < 10; i++) {
a[i] = (function () {
return i;
})();
}
console.log(a);//(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
四、
变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。
{
let a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
return i;
};
}
console.log(a[0]());//0
}
五、
变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是10。
{
let a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
return i;
};
}
console.log(a[0]());//10
}
2. 代码块{}
3.const
定义的常量不可再次修改;
{
const g=9.8;
g=10;
console.log(g);//Assignment to constant variable.
}
4.解构赋值
eg1面试题:两个变量交换值
(加减法 a=a+b-b;b=a+b-a)
或者([a,b]=[b,a])
或者(声明第三个temp暂存)
let a=1;
let b=2;
/*方法1*/
[a,b]=[b,a];
console.log(a, b);//2,1
/*方法二*/
let c=a+b;
console.log(a, b);
a=c-a;
b=c-b;
console.log(a, b);
按照对应位置,只要结构一致,就对变量赋值。从左至右,如果有未匹配的元素,即解构不成功:
undefined
{
let [a,b,c]=[1,2,3];
console.log(a, b, c);//1 2 3
let [x,y,z]=[1,2];
console.log(x, y, z);//1 2 undefined
let [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo, bar, baz);//1 2 3
}
…
扩展运算符:
标志一个集合(数组),只能是最后一个元素
/*4. ...扩展运算符 */
{
let [a,...c]=[1,2,3];
console.log(a, c);//let [a,b,c]=[1,2,3];
let [...y,x]=[1,2,3];//est element must be last element
}
5.字符串遍历
之前的方法:
let a = "abcdefg";
for (let i = 0; i < a.length; i++) {
console.log(a.charAt(i));//a b c d e f g
}
for (let key in a) {
console.log(a.charAt(key));//a b c d e f g
}
而es6中增加了for of
方法遍历字符串
for(let key of a){
console.log(key);//a b c d e f g
}
6.模板字符串
ctrl+alt+s 选择es6 减少报错
//之前
let a=6;
let s="abc"+a;
console.log(s);//abc6
要加反引号`` 真的很容易出错:abc不用再加双引号,$后要用{},{}里面的变量名不加“”
//es6
let a = 6;
let s = `abc${a}`;
let str = `this is a${a} test` //可以加在任意位置
console.log(s);//abc6
console.log(str);//this is a6 test
7.模板编译:
在html页面解析不了(要在模板页面加载),在node中解析
let data=["张三","李四","王五"];
let template=`//这个符号敲开后不会自动生成加号,而""会
<ul>
<% for(let i=0;i<data.length;i++){%>
<li><%=data[i]</li>
<%}%>
</ul>
`;
console.log(template);//未被解析,原样输出
8.正则的扩展:
.flags
获取修饰符,新指定的修饰符可以覆盖之前
let reg=new RegExp(/abc/i);
let regexp=new RegExp(/abc/i).flags;
console.log(reg);// /abc/i
console.log(regexp);//i
附:正则表达式修饰符
9.函数的扩展;
1)允许直接在参数列表上给默认值
2)与解构赋值结合使用时,参数列表里的赋值用=;调用时的赋值用:
/*9.函数使用*/
//es5中
function show(a,b){
b=b||"默认";
console.log(a, b);
}
show("我是参数一");//我是参数一 默认
// es6中
function show(a,b="默认"){
console.log(a, b);
}
show("我是参数一");//我是参数一 默认
// 与解构赋值结合
function get({x=1,y=2}){
console.log(x, y);
}
get({});//1 2
get({x:3,y:4});//3 4
10.箭头函数
函数名=(参数)=>{返回值})
- 函数有参数:
1个参数
let f=v=>v;
console.log(f(1));//1
// 等价于
let fun=function(v){
return v;
}
多个参数
// 多个参数
let more=(a,b)=>a+b;
console.log(more(3, 4));//7
// 等价于
let more=function(a,b){
return a+b;
}
console.log(more(3, 4));//7
- 不带参数的函数:
//不带参数
let ff=()=>1;
// 等价于
let ff=function(){
return 1;
}
console.log(ff());//1
- 既不带参数也不带返回值
let fff=()=>{
console.log(1);
}
fff();//1
- 返回值是数组:
let f=()=>[1,2,3];
console.log(f());//(3) [1, 2, 3]
返回值是对象:要在返回值外加括号
let f=()=>({a:1,b:2});
console.log(f());//{a: 1, b: 2}
箭头函数与解构赋值结合使用
let f=({a,b})=>{
console.log(a, b);
}
f({a:1,b:2});//1 2
重点:箭头函数this
指针保持前后一致
Ps:
map的参数为:value,index,值在前,索引在后
let arr=[9,8,7,6,5];
arr.map((val,index)=>{
console.log(val, index);
console.log(this);//window
})
例如settimeout
计时器this
指针的修改
{
function person(){
this.getsex=()=>{
console.log(this);
setTimeout(()=>{
//在修改为箭头函数后this指针和上面一致,指向person而不是window
console.log(this);
},1);
}
}
let p=new person();//new之后修改了this指针为person
p.getsex();
}
练习1:
和上面的案例很像,上面的案例是在
new
对象的时候修改了this
指针,而次案例使用了call
替换this
指针
{
function foo() {
console.log(this);//{id:1}
setTimeout(() => {
console.log(this.id);//保持上下文一致,输出1
}, 100);
}
var id = 21;
foo.call({id:1});//用当前对象替换foo里的this指针
}
练习2:
输出为2是因为第一个
return
函数没有使用箭头函数,所以不会和上文一致变为id:1
function foo() {
console.log(this)//id:1
return function (){
console.log(this)//id:2
return () => {
return () => {
console.log('id:', this.id);//2
};
};
}
}
var id=100;
var f = foo.call({id: 1});//替换最外层函数的指针为{id: 1}
var t1 = f.call({id: 2})()(); // 替换第一个return函数下的指针为{id: 2}
练习3:
输出为1是因为第一个
return
使用箭头函数,所以和上文一致变为id:1
function foo() {
console.log(this)//id:1
return ()=>{
console.log(this)//id:1
return () => {
return () => {
console.log('id:', this.id);//1
};
};
}
}
var id=100;
var f = foo.call({id: 1});//替换最外层函数的指针为{id: 1}
var t1 = f.call({id: 2})()(); // 替换第一个return函数下的指针为{id: 2}
箭头函数不适用 的两个场景:
在对象里面的函数(方法内包含this
)
调用
cat.jumps()
时,如果是普通函数,该方法内部的this
指向cat
;如果写成上面那样的箭头函数,使得this指向全局对象,因此不会得到预期结果。
const cat = {
lives: 9,
jumps: () => {
console.log(this);//window
this.lives--;
}
}
cat.jumps();
正常使用时
const cat = {
lives: 9,
jumps: function() {
console.log(this);//{lives: 9, jumps: ƒ}
this.lives--;
}
}
cat.jumps();
dom对象的事件(需要动态的this时)
正常情况
var button = document.getElementsByClassName('press')[0];
button.addEventListener('click', function() {
console.log(this);//<button class="press on">按钮</button>
this.classList.toggle('on');
});
修改后由于this指针改变,浏览器报错Cannot read property 'toggle' of undefined
var button = document.getElementsByClassName('press')[0];
button.addEventListener('click', ()=> {
console.log(this);//window
this.classList.toggle('on');
});
箭头函数的嵌套
改写1:
/* function Data(){
return {
getInfo:function (){
return "你好";
}
}
}*/
let f=()=>({getinfo:()=>"这是一个改写测试"});
console.log(f().getinfo());//这是一个改写测试
11.严格模式
浏览器如果版本过高已经不会报错
"use strict";
//优点 提高代码的安全性 优化代码 提高运行速度
x = 3.14; // 报错 (x 未定义)
console.log(x);
12.异常处理
在任何情况下,
finally
块中的代码都会执行,不论try
块中的是否出现异常或者是否被捕获;
$("button").click(function () {
try {
//抓异常
//出现异常 会抛出throw异常
let num = $("input").val();
if (num < 0) {
throw new Error("输入的值不能小于0!");
}
else {
alert(Math.sqrt(num));
}
}
catch (err) {
console.log(err);
}
finally {
console.log("最后执行");
}
});
注意抛出异常时的
new Error
语句和catch
中的参数!
13.super
this
关键字总是指向函数所在的当前对象,ES6
又新增了另一个类似的关键字super
,指向当前对象的原型对象。只能用在对象的方法之中,用在其他地方都会报错。
const popinfo = {
hello: "bar"
}
const world = {
hello:"my",
gethello(){
//获取到原型链上的hello
//super.hello 指的是world 原型链上的hello
return super.hello;
}
}
Object.setPrototypeOf(world,popinfo);//target proto 将popinfo追加为world的原型链上
console.log(world.gethello());//bar