From es6 entry to the first blood of the five consecutive peerless

Welcome to e6 Grammar Notes Teaching

  1. ES6, the full name of ECMAScript 6.0, is the next version of JavaScript standard, released in 2015.06. Those who come to study should have a certain understanding of it, so I won’t make too many statements here. This post is mainly based on the study notes made from "ES6 from Confused to Flexible Use".
  2. The recording method of this blog is to record the main points of es6 through the demo, with detailed comments, and the running results have also been noted. There may be little technical discussion, and it is mainly for es6 beginners. The length may be very long, but each node is clearly distinguished, and you can Choose to learn...
  3. Originally, I wanted to write a full blog, but found it a bit difficult, which is not conducive to positioning queries. Therefore, in this chapter, the catalog query is as follows, and the catalog icon on the right side of the blog:
    insert image description here

1. Variable declaration

1.1. There are three ways to declare variables

<script type="text/javascript">
	var price = 100;
	let age = 20;
	const id = 'abc123';
</script>

1.2. Block-level scope in JS, the difference between var, let, and const

Reference: https://blog.csdn.net/hot_cool/article/details/78302673#commentBox

1.2.1, the definition of var

<script type="text/javascript">
	//1、var声明的变量是可以重新赋值和重复声明的
	var price = 100;
	price = 80;		//重新赋值
	var price = 50;		//重复声明
	console.log(price);//50
	
	//2、作用域简析
	{
    
    
	//块级作用域定义
		var minPrice = 100;
	}
	console.log(minPrice);//全局作用域中可见,打印100,可跨块
	
	//函数块中定义
	function getPrice(){
    
    
		var maxPrice = 200;
		console.log(maxPrice);
	}
	getPrice();//调用函数,函数中可见打印200
	
	//全局中不可见,Error,则跨函数不能访问
	console.log(maxPrice);
	
</script>

1.2.2 Definition of let and coust

The main function of the title let and coust definition is in the block-level { } scope, while const defines constants, which cannot be modified once defined.

<script type="text/javascript">

	//1、常量和变量的区别
	let apple = 5;
	//let apple = 20;	//SyntaxError,不能重复声明
	apple = 8; 	//重新赋值是可以的
	
	const banana = 5;	//一经定义,必须初始化赋值
	//const banana = 8;  //SyntaxError,不能重复声明
	//banana = 8; 	//TypeError,常量一经定义赋值就无法修改
	

	//2、不同的作用域,看似重复定义,前提是定义的变量不能跨域
	let pear = 5;	//全局作用域中
	{
    
    
		let pear = 8;	//块级作用域中
	}


	//3、使用场景
	var price = 100;
	var count = 6;
	if(count > 5){
    
    
		//discount只是作为临时变量,执行完就销毁,故不用var ,而let,const都可以定义在当前块中即可
		let discount = price * 0.6;
		console.log(`The discount is ${
      
      discount }`);//es6 字符串的拼接
	}
	console.log(discount);//ReferenceError,已销毁
	
</script>

const defines object resolution:

<script type="text/javascript">

	//关于const对象引用
	const person = {
    
    'name':'tom','age':'5'};
	console.log(person);	//{name: "tom", age: "5"}

	//重新赋值一个对象的引用,也就是改变成另一个人,当然不行
	//person = {'name':'Jerry','age':'4'}; //TypeError

	//这个修改引用对象中的属性值,person所指向的原始引用是没变化的,所以 no problem
	person.name = '大鱼';
	console.log(person);	//{name: "大鱼", age: "5"}

</script>

Analysis of memory pollution problem

<script type="text/javascript">

	//console.log(name);	//并未报错,而是null,这里打印的其实是 window 对象的name
	var name = "tom";
	//js以前版本,只有var定义,由于其可重复声明,则可能覆盖掉已定义的变量,造成内存污染,如果此处用let,就会报错提示了
	console.log(name);//tom
	console.log(window.name);//tom
</script>

Solution:
The explanation of the case analysis is not deep enough, please forgive me...

<script type="text/javascript">
	//1、IIFE(立即调用函数表达式),利用返回值接受
	//参考地址:https://developer.mozilla.org/zh-CN/docs/Glossary/%E7%AB%8B%E5%8D%B3%E6%89%A7%E8%A1%8C%E5%87%BD%E6%95%B0%E8%A1%A8%E8%BE%BE%E5%BC%8F
	var result = (function () {
    
    
	    var name = "Barry";
	    return name;
	})();
	console.log(result);// "Barry"
	console.log(window.name);// 打印结果为空


	//2、利用块级作用域{ }
	{
    
    
		//注意:利用块级作用域当然只能使用let,const定义,用var定义会跨域,同样会污染全局作用域中的变量
		let name = "Barry";
		console.log(name);
	}
	console.log(window.name);// 打印结果为空



	//3、经典案例解析
	/*
		可以看出每次console.log(i) 打印是正常的,因为其执行顺序的原因
		而定时器执行时,var定义的 i 自身都在全局作用域,且可以重定义,i 最后输出值为4,再执行 i++,i的值为5,跳出循环
		--则定时器开始打印时,i已经是5,循环了5次,打印5个5
	 */
	for(var i=0;i<5;i++){
    
    
		console.log(i);		// 0 1 2 3 4
		//定时器1秒后执行
	    setTimeout(function() {
    
    		// 5 5 5 5 5
	       console.log(i);
	    }, 1000);
	}


	/*
	   这种打印结果是不是你想要的,因为 let 是定义在块级作用域
	   则for循环的 { } 循环体会创建 5 次,各个之间互不干扰,就是如下输出
	 */
	for(let i=0;i<5;i++){
    
    
		console.log(i);		// 0 1 2 3 4
		//定时器1秒后执行
	    setTimeout(function() {
    
    		// 0 1 2 3 4
	       console.log(i);
	    }, 1000);
	}

</script>

1.2.3, Temporal Dead Zone (TDZ) temporary dead zone

<script type="text/javascript">

	/*
		1、首先看下面的代码,在声明之前使用了变量color,打印却没有报错!
		--因为这是在js中存在变量提升,也就是在当前作用域声明的变量会被提升到作用的顶部
	 */
	console.log(color);		// undefined
	var color = 'yellow';

	//2、上面变量提升效果实际上等同于这样
	var color;				//变量提升,只是声明了变量,并未赋值
	console.log(color);		// undefined
	color = 'yellow';


	/*
		3、现在测试一下 let,const 同理不做演示
		  -- 未定义导致的错误,其实在let中也存在变量提升,但是在let和const中还存在一个叫做 “临时性死区” 的概念。
		  在这个作用域的开始直到变量的声明之前,这个变量都是处在 “临时性死区” 当中的,这个时候引用他的话会报referenceError的错误,
		  其实这个特征可以帮助我们养成在变量未声明之前不要使用它的好习惯
	 */
	console.log(book);		//ReferenceError
	let book = 'cat';

</script>

Seeing this, I have a small idea in mind for the selection of variables in es6. When rebinding or updating is required, let is used. Constants are const. Try not to use var, because var may generate some repeated declarations. And using it before it's defined is less easy to find bugs, so try to use const and let instead.

Two, Arrow Function arrow function

2.1. Concise grammar

 <script type="text/javascript">
	//1、基本写法。利用Array.map()函数循环
	const numbers = [5, 9, 13, 25, 30, 7, 11];
	const double = numbers.map(function(number){
    
    
		return number * 2;
	});
	console.log(double); // [10, 18, 26, 50, 60, 14, 22]


	//2、箭头函数改写
	const double2 = numbers.map((number) => {
    
    
		return number * 2;
	});
	console.log(double2); // [10, 18, 26, 50, 60, 14, 22]


	//2.1、如果箭头函数的传入参数只有一个,那么是可以不写括号的
	const double3 = numbers.map(number => {
    
    
		return number * 2;
	});


	//2.2、如果多个参数,以逗号分割。例如新增打印索引
	const double4 = numbers.map((number, i) => {
    
    
		return `${
      
      i}${
      
      number * 2}`;
	});
	console.log(double4);//["0:10", "1:18", "2:26", "3:50", "4:60", "5:14", "6:22"]


	//2.3、如果没有传入参数,则()是需要保留的
	const double4 = numbers.map(() => {
    
    
		return `Hello World`;
	});
</script>

2.2. Implicit return

<script type="text/javascript">

	const numbers = [5, 9, 13, 25, 30, 7, 11];
	/*
		箭头函数的隐式返回
			1、删除 return 关键字
			2、去掉方法体的 {}
			3、并做一行
	 */
	const double = numbers.map(number => number * 2);
	console.log(double);//[10, 18, 26, 50, 60, 14, 22]

</script>

2.3. Anonymous function

<script type="text/javascript">

	//1、显示函数定义
	function getName(name){
    
    
		alert(`hello,${
      
      name}!`);
	}
	//函数调用
	getName("tom");


	//2、箭头函数是一个匿名函数,所以通常使用变量接受其返回值,然后打印即可
	const getname = name => alert(`hello,${
      
      name}!`);
	//变量传入参数name调用
	getname("jerry");

</script>

2.4. The this value of the arrow function

<script type="text/javascript">

	/*
		1、this 对象是在程序运行时绑定的
			printHobbies() 中的this 是Jerry 对象调用,所以绑定的是Jerry
			Array.map() 是一个独立的函数,独立运行时是不作为对象的方法调用的,故直接绑定到顶层的 window 对象

	 */
	const Jerry = {
    
    
		name: "Jerry",
		hobbies: ['Coding','Sleeping','Reading'],
		printHobbies: function(){
    
    
			console.log(this);		//打印的是 Jerry 对象

			this.hobbies.map(function(hobby){
    
    
				console.log(this);	// 打印的是 window 对象
				console.log(`${
      
      this.name} love ${
      
      hobby}`);	//循环分别打印 love Coding;love Sleeping;love Reading
			});
		}
	}
	Jerry.printHobbies();


	/*
		2、改为箭头函数打印如下:
			是因为箭头函数没有自己的 this 绑定,默认是继承父作用域的 this 值
			箭头函数this值是词法作用域,定义时即指定,以后也不会随调用方法的改变而改变
	 */
	const Tom = {
    
    
		name: "Tom",
		hobbies: ['Coding','Sleeping','Reading'],
		printHobbies: function(){
    
    
			console.log(this);		//打印的是 Tom  对象
			this.hobbies.map(hobby => {
    
    
				console.log(this);	// 打印的是 Tom  对象
				console.log(`${
      
      this.name} love ${
      
      hobby}`);	//Tom love Coding;Tom love Sleeping;Tom love Reading
			});
		}
	}
	Tom.printHobbies();

</script>

2.5. When the arrow function is not applicable

1. Although the arrow function is very convenient to use, there are also the following situations where it is not applicable. The following examples are as follows:

<script type="text/javascript">

	//1、作为构造函数,需要绑定this对象
	const Person = (name, age) => {
    
    
		this.name = name;
		this.age = age;
	}
	const Jerry = new Person('Jerry', 23);//TypeError: Person is not a constructor8


	//2、为Person 对象添加方法,需要this指定当前对象
	Person.prototype.updateAge = () => {
    
    
		console.log(this); 		//this 绑定的是父级对象,window
		this.age ++;
		console.log(this.age);	// NaN
	}
	console.log(Jerry.updateAge());


	//3、当真的需要 this 值的时候
	const button = document.querySelector('.zoom');	//获取一个 class='.zoom'的元素对象
	button.addEventListener('click', () => {
    
    
		console.log(this);			//window
		this.classList.add('in');	//当前绑定的对象添加一个 in 样式

		setTimeout(() => {
    
    			//两秒后移出当前 in 样式
			this.classList.remove('in');
		}, 2000);
	});


	//4、需要使用 arguments 对象,arguments就是传入的实参,js中每个函数都具有
	const sum = () => {
    
    
		return Array.form(arguments)	//将传入的实参格式化成一个数组对象
		/*
		 reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,
		 接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组
		 	prevSum : 每次回调函数的返回值(prevSum + value的值)
		 	value 	: 当前迭代数组中的元素值
		 	0 : 从指定下标处开始计算,一般还是记作0

		 	可参考:https://blog.csdn.net/Web_J/article/details/88870515
		 */
				.reduce((prevSum, value) => prevSum + value, 0);
	}
	console.log(sum(1, 2, 3));	//ReferenceError: arguments is not defined

</script>

2. The operation of changing the above 4 use cases back to the original function is as follows:

<script type="text/javascript">

	//1、作为构造函数,需要绑定this对象
	const Person = function(name, age){
    
    
		this.name = name;
		this.age = age;
	}
	const Jerry = new Person('Jerry', 23);
    console.log(Jerry);     //Person {name: "Jerry", age: 23}


	//2、为Person 对象添加方法,需要this指定当前对象
	Person.prototype.updateAge = function(){
    
    
		this.age ++;
		console.log(this.age);	   // 24
	}
	Jerry.updateAge();


	//3、当真的需要 this 值的时候
	const button = document.querySelector('html');
	button.addEventListener('mousedown', function(){
    
    
		console.log(this);			// this对象
		this.classList.add('in');
		setTimeout(() => {
    
    
            console.log(this);         // 需要注意的是这里绑定父级对象,即定义的 button
			this.classList.remove('in');
		}, 2000);
	});


	//4、需要使用 arguments 对象,arguments就是传入的实参,js中每个函数都具有
	const sum = function(){
    
    
		return Array.from(arguments)	//将传入的实参格式化成一个数组对象
				.reduce((prevSum, value) => prevSum + value, 0);
	}
	console.log(sum(1, 2, 3));	//6

</script>

3. Function parameter default value

<script type="text/javascript">

	// 1、 es6 之前给参数赋默认值
	function multiply(a, b){
    
    
		/*
			赋值默认参数,a 传入值则为其本身赋值,a 没有传入值赋默认值5
			注意:js中参数默认是声明的,不能重复声明
		 */
		//const a = a || 5; //SyntaxError
		a = a || 5;
		b = b || 3;
		return a * b;
	}
	console.log(multiply(2, 4));	//传入参数,打印 8
	console.log(multiply());	//使用默认参数,打印 15


	/*
		2、 es6 写法
			2.1、可减少代码量
			2.2、可简明发现哪些代码是可以省略的,提高代码的可读性
	 */
	function multiply2(a = 5, b = 3){
    
    
		return a * b;
	}
	console.log(multiply2(2, 4));	//打印 8
	console.log(multiply2());	//打印 15

	//传入第一个参数写法
	console.log(multiply2(4));	//打印 12

	/*
		参入的参数不是第一个,则前面的参数值要是使用默认值,需用undefined代替传入
		内部实现: typeof a === undefined 才能使用默认值
	 */
	 console.log(multiply2(undefined, 4));	//打印 20

	 //console.log(multiply2(null, 4));	//不行,打印 0

</script>

Fourth, the template string (Template StringsLiterals)

4.1. Introduction to template strings

4.1.1. Basic syntax

<script type="text/javascript">

    //1、使用一对反引号包裹,简单明了不易出错
    const person = 'Jerry';
    let age = 23;
    const sentence = person + ' is ' + age + ' years old'; //字符串拼接易出错
    console.log(sentence);  //Jerry is 23 years old

    /*
        相对于传统更显简洁,便利
            1、一对反引号包裹所有的字符串内容
            2、字符串中引用变量,表达式使用 ${} 包裹即可
     */
    const sentence1 = `${
      
      person} is ${
      
      age * 5} years old`;
    console.log(sentence1);    //Jerry is 115 years old


    //2、定义模板,能更好的体现其层级关系
    const template = `
        <div class="greet">
            <p>Hello</p>
        </div>
    `.trim();   //模板字符串会保留里面的空格,可用trim()去掉字符串前后空格
    console.log(template);

</script>

4.1.2. Example demonstration

Among them, template strings are nested in template strings , which are shown in the comments explaining the join() method, but in actual operation, comment them out to perform encapsulation and decoupling operations by methods.

<script type="text/javascript">

    //1、字符串模板的案例
    const Jelly = {
    
    
        name: 'Jelly',
        date: '2019-08-19',
        todos: [
            {
    
     name: 'Go to Store', completed: false},
            {
    
     name: 'Watch Movie', completed: true},
            {
    
     name: 'Running', completed: true}
        ]
    }

    /*
        join() 方法用于把数组中的所有元素放入一个字符串。✔
        元素是通过指定的分隔符进行分隔的(本数数组默认已逗号分割)
        语法:arrayObject.join(separator) ,separator 可选,指定要使用的分隔符。如果省略该参数,则使用逗号作为分隔符

    const template = `
        <strong>${Jelly.name}</strong>
        <ul>
            ${Jelly.todos.map(todo => `<li>${todo.name},${todo.completed ? '✔':'✘'}</li>`).join('')}
        </ul>
        <strong>${Jelly.date}</strong>
    `;*/


    //将上面注释的代码,进行解耦操作,同时也跟有利于代码的解读
    function renderTodos(todos){
    
    
        return (
            `<ul>
                ${
      
      todos.map(todo => `<li>${
      
      todo.name}${
      
      todo.completed ? '✔':'✘'}</li>`).join('')}
            </ul>
            `
        )
    }

    //${} 中调用方法
    const template = `
        <strong>${
    
    Jelly.name}</strong>
        ${
    
    renderTodos(Jelly.todos)}
        <strong>${
    
    Jelly.date}</strong>
    `;

    document.body.innerHTML = template;


</script>

4.2, tag template string

4.2.1. Definition and examples of tag template strings

A highlighted css style is written here. If you use style use cases later, I will try to use this. In order to save space, this highlighted style will not be posted later .

<style>
    .highlight{
    
    
        padding: 2px 5px;
        background: #00adb4;
        color: white;
    }
</style>
<script type="text/javascript">

    //1、标签模板字符串

    /*
        这个方法参看下面定义 const sentence = ...;
            根据标签模板字符串的定义进行构造的函数,sentence 会得到函数 highlight() 的返回值

        参数讲解:
            1、string  --模板字符串中的 `` 包裹的字符串
            2、user    --模板字符串中 ${user} 变量值
            3、topic    --模板字符串中 ${topic} 变量值
     */
    //function highlight(string, user, topic){ }


    //根据上面的方法,如果有多个变量参数,显然不适用,使用es6剩余参数改写
    // 三个点加上变量名,values是一个数组哦
    function highlight(strings, ...values){
    
    
        //debugger; //可手动解开此注释进行调试,如下图
        const highlighted = values.map( value => `<span class='highlight'>${
      
      value}</span>`);
        let str = '';
        //这个拼接有点意思,${string} 第一次是 null,第三次也是null, ${highlighted[i]}第3次是undefined,使用默认值填补''
        //strings.forEach((string, i) => str += `${string}${highlighted[i] || ''}`);

        //对上面的 forEach 函数用 reduce 改写
        str = strings.reduce((prev, curr, i) => `${
      
      prev}${
      
      curr}${
      
      highlighted[i] || ''}`,'');
        return str;

    }

    const user = 'Mary';
    const topic = 'Learn to use markdown';

    //标签(highlight,对应js的函数名)模板字符串(``中的内容,对应js函数中的参数)
    const sentence = highlight`${
      
      user} has commented on your topic ${
      
      topic}`;

    document.body.innerHTML = sentence;


</script>

Here is the interface effect of enabling debugger debugging in the above js, which is very important as a front-end debugging, hope to know and learn;
insert image description here

4.2.2. Input string filtering to prevent XSS attacks

// 引入 dompurify 过滤工具
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/1.0.11/purify.min.js" type="text/javascript"></script>

<script type="text/javascript">

    //标签模板字符串过滤用户注入脚本,预防xss攻击

    //以下内容简单模拟
    let user = "Mary";//当前用户

    //假设用户在你的输入文本框中输入了如下内容,提交后台之前你使用js获取了用户提交的内容
    let content = 'Hello,Cutie! <br/><img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1566375153572&di=c1a298fbb9ed56dca31f61ca8602ed2b&imgtype=0&src=http%3A%2F%2Fi3.hexunimg.cn%2F2014-12-10%2F171277207.jpg" οnlοad="alert(`大吉大利,今晚抓鸡`);" />';


    //1、如果对用户提交不处理,请解开下面注释查看效果
    //document.body.innerHTML = content;


    //2、以下内容为使用DOMPurify过滤的操作效果
    function sanitize(strings, ...values){
    
        //其实下面的拼接思想的核心是,模板字符串 strings 数组的生成是通过此模板字符串中的变量 ${} 分割的

        // 这一步是将要展示的模板字符串进行拼接
        const dirty = strings.reduce((prev, curr, i) => `${
      
      prev}${
      
      curr}${
      
      values[i] || ''}`,'');
        // 这一步就是调用 Purify 的方法将要打印的字符串 dirty 过滤
        return DOMPurify.sanitize(dirty);
    }


    // 标签模板字符串:将要打印的数据 通过调用自定义函数 sanitize 进行处理
    // 此处过滤掉 js ,界面已无弹窗警告
    document.body.innerHTML = sanitize`
        <span class="highlight">${
      
      user}</span>
        <div style="width:80px;height:50px;" >
            ${
      
      content}
        </div>
    `;

</script>

4.3, es6 new string method

  • startsWith(): returns a Boolean value indicating whether the parameter string is at the head of the original string.
  • endsWith(): Returns a Boolean value indicating whether the parameter string is at the end of the original string.
  • includes(): Returns a boolean indicating whether the parameter string was found.
  • repeat() : replicates the string the specified number of times
<script type="text/javascript">

    const id = '51030019801106542x';
    const fan = 'I Love Laravist';

    //1、startsWith() 从头部判断
    console.log(id.startsWith('51'));   //判断id是否51开头,true
    console.log(id.startsWith('1980',6));  // id 第6位是否1980开头,true

    // startsWith 是大小写敏感的
    console.log(fan.startsWith('I'));   //true
    console.log(fan.startsWith('i'));   //false


    //2、endsWith() 从尾部判断,同理
    console.log(id.endsWith('x'));   //true
    console.log(id.endsWith('X'));   //false

    console.log(fan.endsWith('Love',6));//true, 这里从尾部开始计算,这里的6传入的是从I往后数 e 的位置,空格也要算一位


    //3、includes() 判断是否查找到指定字符串
    console.log(fan.indexOf('Laravist')!=-1);   // true, es6以前判断fan中是否存在指定字符串'Laravist'
    console.log(fan.includes('Laravist'));      // true,直接判断
    console.log(fan.includes('Laravist',10));      // false,判断第10位之后是否还存在指定字符串


    //4、repeat() 复制字符串指定的次数
    console.log('哈'.repeat(5)); //哈哈哈哈哈 ,将'哈'复制5次打印

    //4.1、美化字符串
    const heading = `${
      
      '='.repeat(5)}${
      
      fan}${
      
      '='.repeat(5)}`;
    console.log(heading);       //=====I Love Laravist=====

    //4.2、实现字符串右对齐
    function padder(string, length=25){
    
     //默认总长度为25

        /*
            Math.max():函数返回一组数中的最大值。如果给定的参数中至少有一个参数无法被转换成数字,则会返回 NaN。

            ' '字符复制次数为 (length-string.length),0  这两个数中最大的那个数

            注:再传入一个0的意义是防止,出现负数,而导致repeat()函数出现 RangeError: Invalid count value
         */
        return `${
      
      ' '.repeat(Math.max(length-string.length, 0))}${
      
      string}`;
    }

    console.log(padder(id));    //      51030019801106542x
    console.log(padder(fan));   //         I Love Laravist

</script>

Guess you like

Origin blog.csdn.net/w2462140956/article/details/97904823