ES6知识点归纳(一)——var、let、const、箭头函数、函数参数的默认值、ES6模版字符串

参考书籍:http://es6.ruanyifeng.com/
参考视频:https://www.bilibili.com/video/av47304735
全部篇章:
ES6知识点归纳(一)——var、let、const、箭头函数、函数参数的默认值、ES6模版字符串
ES6知识点归纳(二)——对象解构、数组解构、for of循环、新增的方法、剩余参数、扩展运算符
ES6知识点归纳(三)——Promise、Symbol、模块(Modules)、class继承、Iterator、Generator、Proxy、Set、WeakSet、Map、WeakMap


var、let、const

var

  1. 可以重复声明、可以重新赋值
  2. 在函数中声明变量,则只能在函数中使用(var 声明的变量的作用域属于 Function Scope)
  3. 用 var 在 if 语句的代码块中声明,因为没有函数,所以在 if 语句的代码块外也能访问
function hi() {
  if (true) {
    var i = "hi";
    console.log(i); //hi
  }
  console.log(i); //hi
}
hi();
console.log(i); //delete.html:26 Uncaught ReferenceError: i is not defined
  1. 存在变量提升,声明的语句会被提升到作用域最上方,赋值语句不被提升,留在原地
console.log(i);
var i = 1; //undefined

//相当于
//var i;
//console.log(i);
//i=1;

注意:

for (var i = 0; i < 5; i++) {
  console.log(i); //0 1 2 3 4,这行语句在for循环执行的时候立即执行
  setTimeout(function() {
    console.log(i); //5 5 5 5 5 ,for循环结束后执行
  }, 0);
}
  • 解决方法就是改用 let

let

  1. 不可以重复声明、可以重新赋值
  2. 用 let 声明变量,只在代码块内可访问(let 声明的变量的作用域属于 block scope)
    let count = 10;
    let discount = 0.9;
    const key = "abc";
    if (count > 5) {
      let discount = 0.5;
      console.log(discount); //0.5
    }
    console.log(discount); //0.9
    
    let count = 10;
    let count = 1;
    // Uncaught SyntaxError: Identifier 'count' has already been declared
    
  3. 存在变量提升,但因为存在作用域死区(Temporal dead zone),但是若想在当前块级作用域中,这个变量声明之前引用这个变量,就会报错。
    • 在这个作用域开始直到这个变量声明之前,这个变量都处在临时性死区当中,这时引用它会报 ReferenceError

const

  1. 不可以重复声明、不可以重新赋值
  2. 用 const 声明时必须立刻赋值
  3. 用 const 声明变量,只在代码块内可访问(属于 block scope)
    const key = "123";
    key = "456"; //delete.html:19 Uncaught TypeError: Assignment to constant variable.
    
    const key;//Uncaught SyntaxError: Missing initializer in const declaration
    
    if (true) {
      const key = "123";
      console.log(key); //123
    }
    console.log(key); //delete.html:22 Uncaught ReferenceError: key is not defined
    

注意:这样也是不可以的

let i = 0;
const i = 1; //Uncaught SyntaxError: Identifier 'i' has already been declared
  1. 若用 const 声明时,给它的是一个对象,那么,对象的属性仍能改变,因为 const 指向的是对象的引用,这个引用不能变
const person = {
  name: "Alred",
  age: 30
};
person = {
  name: "Alfred"
};
//delete.html:22 Uncaught TypeError: Assignment to constant variable.
const person = {
  name: "Alred",
  age: 30
};
person.age = 20;
console.log(person); //正常输出且不报错,其中age为20
  • 也可以这样赋值
let abc = {
  name: "Raymond"
};
const person2 = abc;
  • 若希望对象的属性值也不修改的话,可以使用 Object.freeze()方法
const person = {
  name: "Alred",
  age: 30
};
Object.freeze(person); //不允许改变对象的属性值
person.age = 20;
console.log(person.age); //30
  1. 存在变量提升,也存在作用域死区(和 let 一样)

三者如何选择

  • 默认使用 const
  • 当变量需要重新绑定或更新的时候使用 let
  • 在 ES6 中尽量不适用 var

箭头函数

语法简明

    () => { ... } // 没有参数
    x => { ... } // 一个参数,括号可加可不加(x)=>{...}
(x, y) => { ... } // 多个参数

简单例子

const numbers = [1, 2, 3, 4, 5];
const double = numbers.map(function(number) {
  return number * 2;
});

const double2 = numbers.map(number => {
  return number * 2;
});
console.log(double); // [2, 4, 6, 8, 10]
console.log(double2); // [2, 4, 6, 8, 10]

可以隐式返回

x => {
  return x * x;
}; // 语句块
x => x * x; // 表达式,和上一行作用相同
const numbers = [1, 2, 3, 4, 5];
const double = numbers.map(number => {
  return number * 2;
});
const double2 = numbers.map(number => number * 2);
console.log(double); // [2, 4, 6, 8, 10]
console.log(double2); // [2, 4, 6, 8, 10]

this

  1. 箭头函数没有自己的 this 值,它的 this 是继承它的父作用域的(即上层作用域)
  2. 箭头函数在指定的时候 this 已经确定,一般情况下不会因为调用而改变,不过会随上层作用域的 this 的变化而变化
  • 先看一个例子
const Alfred = {
  name: "Alfred",
  hobbies: ["singing", "dancing", "composeing"],
  printHobbies: function() {
    console.log(this);
    this.hobbies.map(function(hobby) {
      console.log(this); //window
      console.log(`${this.name} loves ${hobby}`); //输出内容都缺了Alfred
    });
  }
};
Alfred.printHobbies();

调用 Alfred 中的 printHobbies(),第一个 this 指向 Alfred,然后 printHobbies 里的那个函数,是 map 方法的一个回调函数,这个方法是独立运行的,因此这个方法指向的是 window

  • 解决方法
const Alfred = {
  name: "Alfred",
  hobbies: ["singing", "dancing", "composeing"],
  printHobbies: function() {
    var _this = this;
    this.hobbies.map(function(hobby) {
      console.log(this);
      console.log(`${_this.name} loves ${hobby}`);
    });
  }
};
Alfred.printHobbies();

或者,使用箭头函数

const Alfred = {
  name: "Alfred",
  hobbies: ["singing", "dancing", "composeing"],
  printHobbies: function() {
    this.hobbies.map(hobby => {
      console.log(this);
      console.log(`${this.name} loves ${hobby}`);
    });
  }
};
Alfred.printHobbies();
  • 另外:由于箭头函数是匿名函数,所以一般会把函数赋值给一个变量
const greet = name => {
  console.log(name);
};
greet("Alfred");

箭头函数的不适用场景

  1. 不能作为构造函数,不能用于定义对象方法
// const person = (name, points) => {       //Uncaught TypeError: person is not a constructor
const person = function(name, points) {
  this.name = name;
  this.points = points;
};
const Alfred = new person("Alfred", 30);
// person.prototype.updatePoints = () => {
//     console.log(this);//Window,因为箭头函数不会绑定this,但是方法又需要绑定到对象上,因此不能用
//     this.points--;
//     console.log(this.points);
// }
// Alfred.updatePoints(); //NaN
person.prototype.updatePoints = function() {
  console.log(this); //person
  this.points--;
  console.log(this.points);
};
Alfred.updatePoints(); //29
  1. 真的需要用到 this 的时候不能使用箭头函数
<div
  id="app"
  style="width: 50px ; height: 50px; background-color: #000000;"
></div>
const app = document.getElementById("app");
// app.addEventListener('click', () => {
app.addEventListener("click", function() {
  //此处的方法需要绑定到app上,但是用箭头函数是不会进行绑定的
  console.log(this); //Window
  this.style.height = "100px";
  setTimeout(() => {
    //此处希望this仍然指向app,使用箭头函数可以使this与外层保持一致
    this.style.height = "50px";
  }, 500);
});
  1. 需要使用 arguments 对象时不能使用箭头函数
// sum函数返回所有参数的和
// const sum = () => {
//     return Array.from(arguments).reduce((preSum, value) => preSum + value, 0)
// }
// sum(1, 2, 3); //delete.html:19 Uncaught ReferenceError: arguments is not defined

const sum = function() {
  return Array.from(arguments).reduce((preSum, value) => preSum + value, 0);
};
console.log(sum(1, 2, 3)); //6

函数参数的默认值

function multiply(a, b) {
  a = a || 5;
  b = b || 3;
  console.log(a * b);
}
multiply(); //15,均使用了默认值
multiply(2, 3); //6,使用了参数的值
multiply(1); //3,b使用了默认值
multiply(undefined, 2); //10,a使用了默认值

用 ES6 可以简化为

function multiply(a = 5, b = 3) {
  console.log(a * b);
}
multiply(); //15,均使用了默认值
multiply(2, 3); //6,使用了参数的值
multiply(1); //3,b使用了默认值
multiply(undefined, 2); //10,a使用了默认值,不能是multiply(, 2);必须要指明前面的参数
multiply(null, 2); //0,不会使用默认值
  • 如果有传参,则使用传进来的值,如果没有传值,函数默认传的是 undefined,if(typeof a === undefined),就会使用默认值

ES6 模版字符串

基础用法

  • 用反引号"`"来定义字符串
  • ${}来引用变量,也可以放表达式、对象的属性、函数
  • 直接使用反引号可以保存 html 代码的层级结构,不需要用\或数组去模拟
  • 模版字符串可以嵌套使用
const person = "Alfred";
const age = 30;
const sentence = person + " is " + age + " years old"; //es5
const sentence2 = `${person} is ${age * 2} years old`; //es6
const template = `
<div>
    <p>Hello</p>
</div>
`.trim();
console.log(sentence);
console.log(sentence2);
console.log(template);

简单应用:

const Alfred = {
  name: "Alfred",
  todos: [
    {
      thing: "Go to the gym",
      completed: false
    },
    {
      thing: "sing a song",
      completed: true
    },
    {
      thing: "dance",
      completed: false
    }
  ]
};
const template = `
<ul>
    ${Alfred.todos
      .map(
        todos => `
        <li>
            ${todos.thing} ${todos.completed ? "(yes)" : "(no)"}
        </li>`
      )
      .join("")}
</ul>
`;
console.log(template);
document.body.innerHTML = template;

根据以上例子,还可以将读取对象内容的代码封装成函数

function renderTodos(todos) {
  return `<ul>
        ${todos
          .map(
            todo => `
            <li>
        ${todo.thing} ${todo.completed ? "(yes)" : "(no)"}
            </li>`
          )
          .join("")}
    </ul>`;
}
const template = `${renderTodos(Alfred.todos)}`;
document.body.innerHTML = template;

标签模版

  • 即在模版字符串中添加标签,根据我们自定义的规则,返回我们想要的字符串
  • 标签对应 js 里的一个函数名
  • 使用标签模版字符串时,最后那个字符串返回的内容是由标签(函数)决定的
  • 这个函数可以接受模版字符串作为参数,第一个参数为模版字符串里的普通字符,其后的参数是模版字符串里的变量
//参数可以用逗号分隔一个一个写
//也可以用ES6中的剩余参数,values是一个数组,是又剩余的参数组成
function hightlight(strings, ...values) {
  // debugger;//可以看到strings,values里有什么
  const hightlighted = values.map(
    value => `<span class='hightlight'>${value}</span>`
  ); //遍历变量的数组,给变量加一个span标签和hightlight样式

  // console.log(hightlighted);

  //将普通字符和处理后的变量拼接在一起
  let str = "";
  // strings.forEach((string, i) => {str += `${string}${hightlighted[i]}`;});
  //由于strings里最后一个是空字符串,因此要改写,以免拼接后句子中出现underfined
  strings.forEach((string, i) => {
    str += `${string}${hightlighted[i] || ""}`;
  });
  return str;
}
const user = "Alfred";
const topic = "Learn ES6";
const sentence = hightlight`${user} has commented on your topic ${topic}`;
//   console.log(sentence);
document.body.innerHTML = sentence;

以上代码优化、简化:

function hightlight(strings, ...values) {
  const hightlighted = values.map(
    value => `<span class='hightlight'>${value}</span>`
  );

  //字符串拼接也可以改为,reduce
  return strings.reduce(
    (prev, curr, i) => `${prev}${curr}${hightlighted[i] || ""}`,
    ""
  );
}
const user = "Alfred";
const topic = "Learn ES6";
const sentence = hightlight`${user} has commented on your topic ${topic}`;
document.body.innerHTML = sentence;

注意:

  1. 如果模版字符串是以变量开头或结尾的话,打印参数 strings,会看到里面有空字符串

forEach():https://www.runoob.com/jsref/jsref-foreach.html
reduce():https://www.runoob.com/jsref/jsref-reduce.html

最佳实践——过滤用户输入(防 xss 攻击)

更多关于标签模版的内容:https://www.cnblogs.com/sminocence/p/6832331.html

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值