文章目录

  • ES5和ES6
    • JSON 方法
    • JSON的两个方法
      • JSON.parse
      • JSON.stringify
    • this 关键字
      • 强行改变 this 指向的方法
        • call
        • apply
        • bind
    • ES6新增的内容
      • let 和 const 关键字
      • 箭头函数
        • 箭头函数的特殊性
      • 函数传递参数的时候的默认值
      • 解构赋值
        • 解构对象
        • 解构数组
        • 注意
      • 模版字符串
      • 展开运算符

ES5和ES6

  • 我们所说的 ES5 和 ES6 其实就是在 js 语法的发展过程中的一个版本而已
  • ECMAScript 就是 js 的语法
    • 以前的版本没有某些功能
    • 在 ES5 这个版本的时候增加了一些功能
    • 在 ES6 这个版本的时候增加了一些功能
  • 因为浏览器是浏览器厂商生产的
    • ECMAScript 发布了新的功能以后,浏览器厂商需要让自己的浏览器支持这些功能
    • 这个过程是需要时间的
    • 所以到现在,基本上大部分浏览器都可以比较完善的支持了
    • 只不过有些浏览器还是不能全部支持
    • 这就出现了兼容性问题
    • 所以我们写代码的时候就要考虑哪些方法是 ES5 或者 ES6 的,看看是不是浏览器都支持

JSON 方法

  • json 是一种特殊的字符串格式,本质是一个字符串

    var jsonObj = '{ "name": "Jack", "age": 18, "gender": "男" }'
    var jsonArr = '[{ "name": "Jack", "age": 18, "gender": "男" }, { "name": "Jack", "age": 18, "gender": "男" }, { "name": "Jack", "age": 18, "gender": "男" }]'
    
  • 就是对象内部的 keyvalue 都用双引号包裹的字符串(必须是双引号)

JSON的两个方法

JSON.parse

  • JSON.parse 是将 json 格式的字符串转换为 js 的对象或者数组

    var jsonObj = '{ "name": "Jack", "age": 18, "gender": "男" }'
    var jsonArr = '[{ "name": "Jack", "age": 18, "gender": "男" }, { "name": "Jack", "age": 18, "gender": "男" }, { "name": "Jack", "age": 18, "gender": "男" }]'var obj = JSON.parse(jsonStr)
    var arr = JSON.parse(jsonArr)console.log(obj)
    console.log(arr)
    
    • obj 就是我们 js 的对象
    • arr 就是我们 js 的数组

JSON.stringify

  • JSON.parse 是将 js 的对象或者数组转换成为 json 格式的字符串

    var obj = {name: 'Jack',age: 18,gender: '男'
    }
    var arr = [{name: 'Jack',age: 18,gender: '男'},{name: 'Jack',age: 18,gender: '男'},{name: 'Jack',age: 18,gender: '男'}
    ]var jsonObj = JSON.stringify(obj)
    var jsonArr = JSON.stringify(arr)console.log(jsonObj)
    console.log(jsonArr)
    
    • jsonObj 就是 json 格式的对象字符串
    • jsonArr 就是 json 格式的数组字符串

this 关键字

  • this 是函数专有的关键词,只有函数才有。

  • 每一个函数内部都有一个关键字是 this ,可以让我们直接使用的。

  • 简单理解,本质上是一个对象,存储数据数值。可以通过操作 this 的语法形式来操作 this 中存储的数据数值。

  • 重点: 函数内部的 this 只和函数的调用方式有关系,和函数的定义方式没有关系

  • 函数内部的 this 指向谁,取决于函数的调用方式

    • this 指向是=> window

      声明式函数、赋值式函数、forEach、定时器、延时器、自调用函数

 function fn() {console.log(this);// 此时 this 指向 window}fn();   // window.fn(), 此处默认省略window// 赋值式函数const fun2 = function(){console.log( this );// 此时 this 指向 window}fun2();// forEachvar arr = [1,2,3,4,5];arr.forEach( function(){ console.log(this);});// 定时器setInterval( function(){console.log(this)} , 1000 );// 延时器setTimeout(function () {console.log(this);// 此时延时器处理函数里面的 this 指向 window}, 0);//自调用函数(function () {console.log(this);// 此时 this 指向 window})();
  • this 指向是=> 存储this的数组、对象

    在数组、对象中存储的函数,函数的 this 指向是存储 this 的数组或者对象

    1. 所有的 this 关键字,在函数运行时,才能确定它的指向
    2. this 所在的函数由哪个对象调用,this 就会指向谁
    3. 当函数执行时,没有明确的调用对象时,则 this 指向 window
    var obj = {fn: function () {console.log(this);// 此时 this 指向 obj}
    }
    obj.fn();// 数组中的函数 this指向 就是 这个数组本身
    const arr = [100,200,300, function(){console.log(this)} ] ;
    console.log( arr );// 调用数组中的函数程序
    arr[3]() ;
    
  • this 指向是=> 事件源

    事件处理函数中的 this 指向是事件源

    div.onclick = function () {console.log(this);
    }
    // 当你点击 div 的时候,this 指向 div
    

强行改变 this 指向的方法

  • 刚才我们说过的都是函数的基本调用方式里面的 this 指向
  • 我们还有三个可以忽略函数本身的 this 指向转而指向别的地方
  • 这三个方法就是 call / apply / bind

call

  • call 方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向

  • 语法: 函数名.call(要改变的 this 指向,要给函数传递的参数1,要给函数传递的参数2, ...)

    var obj = { name: 'Jack' }
    function fn(a, b) {console.log(this)console.log(a)console.log(b)
    }
    fn(1, 2)
    fn.call(obj, 1, 2)
    
    • fn() 的时候,函数内部的 this 指向 window
    • fn.call(obj, 1, 2) 的时候,函数内部的 this 就指向了 obj 这个对象
    • 使用 call 方法的时候
      • 会立即执行函数
      • 第一个参数是你要改变的函数内部的 this 指向
      • 第二个参数开始,依次是向函数传递参数

apply

  • apply 方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向

  • 语法: 函数名.apply(要改变的 this 指向,[要给函数传递的参数1, 要给函数传递的参数2, ...])

  • 用一个数组作为参数

    var obj = { name: 'Jack' }
    function fn(a, b) {console.log(this)console.log(a)console.log(b)
    }
    fn(1, 2)
    fn.call(obj, [1, 2])
    
    • fn() 的时候,函数内部的 this 指向 window
    • fn.apply(obj, [1, 2]) 的时候,函数内部的 this 就指向了 obj 这个对象
    • 使用 apply 方法的时候
      • 会立即执行函数
      • 第一个参数是你要改变的函数内部的 this 指向
      • 第二个参数是一个 数组,数组里面的每一项依次是向函数传递的参数

bind

  • bind 方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向

  • 和 call / apply 有一些不一样,就是不会立即执行函数,而是返回一个已经改变了 this 指向的函数

  • 语法: var newFn = 函数名.bind(要改变的 this 指向); newFn(传递参数)

    var obj = { name: 'Jack' }
    function fn(a, b) {console.log(this);   console.log(a);     console.log(b);
    }
    fn(1, 2);   //=> 上面的函数会依次输出:Window 、 1、 2
    /*在设定新函数的同时,也可以给形参赋值实参,但是如果设定时绑定了数据,数据就不能修改了,
    所以修改this指向时,一般只修改 this 指向不会同时赋值实参,调用时再赋值实参。*/
    var newFn = fn.bind(obj);
    var newFn2 = fn.bind(obj, 1, 2);
    newFn(3, 4);    //=> 上面的函数会依次输出:Object 、 3、 4
    newFn2(3, 4);   //=> 上面的函数会依次输出:Object 、 1、 2//    这里数据就修改不了
    
    • bind 调用的时候,不会执行 fn 这个函数,而是返回一个新的函数
    • 这个新的函数就是一个改变了 this 指向以后的 fn 函数
    • fn(1, 2) 的时候 this 指向 window
    • newFn(1, 2) 的时候执行的是一个和 fn 一摸一样的函数,只不过里面的 this 指向改成了 obj

ES6新增的内容

  • 之前的都是 ES5 的内容
  • 接下来我们聊一下 ES6 的内容

let 和 const 关键字

  • 我们以前都是使用 var 关键字来声明变量的

  • 在 ES6 的时候,多了两个关键字 letconst,也是用来声明变量的

  • var 的区别

    1. letconst 不允许重复声明变量
    // 使用 var 的时候重复声明变量是没问题的,只不过就是后面会把前面覆盖掉
    var num = 100
    var num = 200
    
    // 使用 let 重复声明变量的时候就会报错了
    let num = 100
    let num = 200 // 这里就会报错了
    
    // 使用 const 重复声明变量的时候就会报错
    const num = 100
    const num = 200 // 这里就会报错了
    
    1. letconst 声明的变量不会在预解析的时候解析(也就是没有变量提升)

      // 因为预解析(变量提升)的原因,在前面是有这个变量的,只不过没有赋值
      console.log(num) // undefined
      var num = 100
      
      // 因为 let 不会进行预解析(变量提升),所以直接报错了
      console.log(num) // undefined
      let num = 100
      
      // 因为 const 不会进行预解析(变量提升),所以直接报错了
      console.log(num) // undefined
      const num = 100
      
    2. letconst 声明的变量会被所有的代码块限制作用范围,letconst 声明的变量如果是在 { } 中,那么作用域也只是在 { } 中。 如果 letconst 声明的变量要在 { } 中赋值 ,
      必须要把变量定义在 { } 外 ,在 { } 中只做赋值操作。

     // var 声明的变量只有函数能限制其作用域,其他的不能限制if (true) {var num = 100}console.log(num) // 100
// let 声明的变量,除了函数可以限制,所有的代码块都可以限制其作用域(if/while/for/...)if (true) {// { } 中使用let声明变量,定义的变量只能在 { } 中调用let num = 100;console.log(num); // 100}console.log(num); // 报错:Uncaught ReferenceError: b is not defined// 在 { } 外定义变量 let b ;if( true ){// 如果必须要在{ }中赋值,在{ }外调用的话// 可以使用let在 { } 外定义变量,在 { } 中做赋值操作。  b = 200 ;console.log(b);      //=> 200}console.log(b);           //=> 200// const 声明的变量,除了函数可以限制,所有的代码块都可以限制其作用域(if/while/for/...)if (true) {const num = 100console.log(num) // 100}console.log(num) // 报错
  1. var 在循环中声明循环变量,始终只有一个循环变量被声明,多次循环是向这一个循环变量重复赋值。也就是循环结束后,始终是有一个循环变量存储最终的数值,在循环之外可以调用使用。
    let 在循环中声明循环变量,每一次循环会声明一个独立的循环变量,独立的循环变量存储不同的数据数值 。也就是循环结束相当于生成了多个循环变量存储不同的数值数据,在循环之外不能调用使用。
  • letconst 的区别

    1. let 声明的变量的值可以改变,const 声明的变量的值不可以改变

      let num = 100
      num = 200
      console.log(num) // 200
      
      const num = 100
      num = 200 // 这里就会报错了,因为 const 声明的变量值不可以改变(我们也叫做常量)
      
    2. let 声明的时候可以不赋值,const 声明的时候必须赋值

      let num
      num = 100
      console.log(num) // 100
      
      const num // 这里就会报错了,因为 const 声明的时候必须赋值
      
    3. let 存储 基本数据类型 ( 布尔、数值、字符串、null、undefined )

      const 存储 引用数据类型( 数组、对象、函数 )

  • demo

    <body><ul><li>我是第一个li</li><li>我是第二个li</li><li>我是第三个li</li><li>我是第四个li</li><li>我是第五个li</li></ul><script>// 获取 ul>li 标签对象var oUlLis = document.querySelectorAll('ul>li');// 通过for循环 给 ul>li 绑定 点击事件for (var i = 0; i <= oUlLis.length - 1; i++) {// i 是 索引下标 // oUlLis[i] 是 标签对象oUlLis[i].addEventListener('click', function () {console.log(i);})}</script>
    </body>
    <!--
    1,  console.log( i )只有在触发点击事件时才会执行,循环的时候只是给每一个 li绑定点击事件,并不会输出i。当触发点击事件时, 循环已经完全执行结束, 此时 console.log( i )输出的数值不是绑定点击事件时 i的数值, 也就不是循环执行时 i的数值,而是循环结束后 i所存储的数值。2,  对于循环中 console.log( i )里面 i的数值,使用 var声明和使用 let声明的结果完全不同。1)var 声明的循环变量, 只会生成一个循环变量 i, 每次循环都会对这一个 i进行重复赋值, 循环结束只有一个循环变量存储最终数值。所以不论点击哪一个 li标签,输出的都是 5。2)let 声明的循环变量, 每次循环生成一个独立的循环变量, 每次循环都会有一个独立的循环变量存储当前循环的数值,循环结束会生成多个独立的循环变量存储不同的数值数据。*本质上还是一个循环变量 i, 只是不同循环是不同的作用域, *在每个作用域里面 i存储不同的数值。所以点击哪一个 li标签,就会输出该标签对应的索引下标。
    -->
    

箭头函数

  • 箭头函数是 ES6 里面一个简写函数的语法方式

  • 重点: 箭头函数只能简写函数表达式,不能简写声明式函数

    function fn() {} // 不能简写
    const fun = function () {} // 可以简写
    const obj = {fn: function () {} // 可以简写
    }
    
  • 语法: (函数的行参) => { 函数体内要执行的代码 }

    const fn = function (a, b) {console.log(a)console.log(b)
    }
    // 可以使用箭头函数写成
    const fun = (a, b) => {console.log(a)console.log(b)
    }
    
    const obj = {fn: function (a, b) {console.log(a)console.log(b)}
    }
    // 可以使用箭头函数写成
    const obj2 = {fn: (a, b) => {console.log(a)console.log(b)}
    }
    

箭头函数的特殊性

  • 箭头函数内部没有 this,箭头函数的 this 是上下文的 this

  • 箭头函数和普通匿名函数的区别:

    1、this 指向不同;

    2、箭头函数 this 指向不能改变。

  • 箭头函数的 this 指向

    1、父级程序的 this 指向

    2、如果没有父级程序 ,或者父级程序没有 this 指向,箭头函数的 this 指向是 window

    // 匿名函数 设定的事件处理函数, this指向是事件源oDiv
    Div.addEventListener( 'click' , function(){ console.log(this);   // oDiv
    });
    // 箭头函数 设定的事件处理函数, this指向是父级程序的this指向
    // 当前点击事件没有父级程序, this指向是 window
    oDiv.addEventListener( 'click' , () => { console.log(this);   // window
    })// 对象中定义的箭头函数
    const obj1 = {name:'张三',age:18,sex:'男',// 匿名函数语法 定义 fun1fun1:function(){// this指向是 存储函数fun1的对象obj1console.log(this);// 匿名函数语法定义的赋值式函数, this指向是 windowconst fun2 = function(){ console.log(this) }fun2() ;// 箭头函数 语法定义的赋值式函数, this指向是 父级程序的this指向// 也就是 fun1函数程序的this指向// 函数fun1 的this指向 也就是 对象obj1const fun3 = () => { console.log(this) }fun3() ;},// 箭头函数语法 定义 fun2/* obj1中定义的函数 fun2是箭头函数语法,this指向是函数 fun2的父级程序, 也就是 obj1这个对象, obj1这个对象没有      this(只有函数才有), 所以 fun2的 this指向是 window*/fun2:()=>{console.log(this);},
    };
    obj1.fun1();
    obj1.fun2();
    
  • 箭头函数内部没有 arguments 这个参数集合

    const obj = {fn: function () {console.log(arguments)},fun: () => {console.log(arguments)}
    }
    obj.fn(1, 2, 3) // 会打印一个伪数组 [1, 2, 3]
    obj.fun(1, 2, 3) // 会直接报错
    
  • 函数的行参只有一个的时候可以不写 () ,其余情况必须写

    const obj = {fn: () => {console.log('没有参数,必须写小括号')},fn2: a => {console.log('一个行参,可以不写小括号')},fn3: (a, b) => {console.log('两个或两个以上参数,必须写小括号')}
    }
    
  • 函数体只有一行代码的时候,可以不写 {} ,并且会自动 return

    const obj = {fn2: () => {console.log('只有一行代码,可以不写');},fn: a => {return a + 10},fun: a => a + 10
    }console.log(obj.fn(10));   //=> 20
    console.log(obj.fun(10));   //=> 20console.log(obj.fn2());
    //=> 只有一行代码,可以不写
    //=> undefined
    // cosnole.log( fn() ) 是输出 fn()的返回值,因为没有return,所以会输出 undefined,
    // 又因为fn()是调用函数,所以也会输出fn里面的console.log()里面的内容。
    
    oDiv.addEventListener( 'click' , function(e){ console.log(e) });// 写成箭头函数
    oDiv.addEventListener( 'click' , e => console.log(e) );
    

函数传递参数的时候的默认值

  • 我们在定义函数的时候,有的时候需要一个默认值出现

  • 就是当我不传递参数的时候,使用默认值,传递参数了就使用传递的参数

    function fn(a) {a = a || 10;console.log(a);
    }
    fn();   // 不传递参数的时候,函数内部的 a 就是 10
    fn(20); // 传递了参数 20 的时候,函数内部的 a 就是 20
    
    • 在 ES6 中我们可以直接把默认值写在函数的行参位置
    function fn(a = 10) {console.log(a)
    }
    fn()   // 不传递参数的时候,函数内部的 a 就是 10
    fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
    
    • 这个默认值的方式箭头函数也可以使用
    const fn = (a = 10) => {console.log(a)
    }
    fn()   // 不传递参数的时候,函数内部的 a 就是 10
    fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
    
    • 注意: 箭头函数如果你需要使用默认值的话,那么一个参数的时候也需要写 ()

解构赋值

  • 解构赋值,就是快速的从对象或者数组中取出成员的一个语法方式

解构对象

  • 快速的从对象中获取成员

    // ES5 的方法向得到对象中的成员
    const obj = {name: 'Jack',age: 18,gender: '男'
    }let name = obj.name
    let age = obj.age
    let gender = obj.gender
    
    // 解构赋值的方式从对象中获取成员
    const obj = {name: 'Jack',age: 18,gender: '男'
    }// 前面的 {} 表示我要从 obj 这个对象中获取成员了
    // name age gender 都得是 obj 中有的成员
    // obj 必须是一个对象
    let { name, age, gender } = obj
    

解构数组

  • 快速的从数组中获取成员

    // ES5 的方式从数组中获取成员
    const arr = ['Jack', 'Rose', 'Tom']
    let a = arr[0]
    let b = arr[1]
    let c = arr[2]
    
    // 使用解构赋值的方式从数组中获取成员
    const arr = ['Jack', 'Rose', 'Tom']// 前面的 [] 表示要从 arr 这个数组中获取成员了
    // a b c 分别对应这数组中的索引 0 1 2
    // arr 必须是一个数组
    let [a, b, c] = arr
    

注意

  • {} 是专门解构对象使用的
  • [] 是专门解构数组使用的
  • 不能混用

模版字符串

  • ES5 中我们表示字符串的时候使用 '' 或者 ""

  • 在 ES6 中,我们还有一个东西可以表示字符串,就是 ``(反引号)

    let str = `hello world`
    console.log(typeof str) // string
    
  • 和单引号好友双引号的区别

    1. 反引号可以换行书写

      // 这个单引号或者双引号不能换行,换行就会报错了
      let str = 'hello world' // 下面这个就报错了
      let str2 = 'hello
      world'
      
      let str = `helloworld
      `console.log(str) // 是可以使用的
      
    2. 反引号可以直接在字符串里面拼接变量

      // ES5 需要字符串拼接变量的时候
      let num = 100
      let str = 'hello' + num + 'world' + num
      console.log(str) // hello100world100// 直接写在字符串里面不好使
      let str2 = 'hellonumworldnum'
      console.log(str2) // hellonumworldnum
      
      // 模版字符串拼接变量
      let num = 100
      let str = `hello${num}world${num}`
      console.log(str) // hello100world100
      
      • `` 里面的 ${} 就是用来书写变量的位置

展开运算符

  • ES6 里面号新添加了一个运算符 ... ,叫做展开运算符

  • 作用是把数组展开

    let arr = [1, 2, 3, 4, 5]
    console.log(...arr) // 1 2 3 4 5
    
  • 合并数组的时候可以使用

    let arr = [1, 2, 3, 4]
    let arr2 = [...arr, 5]
    console.log(arr2)
    
  • 也可以合并对象使用

    let obj = {name: 'Jack',age: 18
    }
    let obj2 = {...obj,gender: '男'
    }
    console.log(obj2)
    
  • 在函数传递参数的时候也可以使用

    let arr = [1, 2, 3]
    function fn(a, b, c) {console.log(a)console.log(b)console.log(c)
    }
    fn(...arr)
    // 等价于 fn(1, 2, 3)
    

JavaScript_ES5和ES6相关推荐

  1. ES6 Proxy 性能之我见

    ES6 Proxy 性能之我见 本文翻译自https://thecodebarbarian.com/thoughts-on-es6-proxies-performance Proxy是ES6的一个强力 ...

  2. ES6变量常量字符串数值

    [转]ES6之变量常量字符串数值 ECMAScript 6 是 JavaScript 语言的最新一代标准,当前标准已于 2015 年 6 月正式发布,故又称 ECMAScript 2015. ES6对 ...

  3. 项目中非常有用并且常见的ES6语法

    今天闲着无事,梳理下ES6常见的语法知识点:除此之外的知识点自行细化和梳理! <!DOCTYPE html> <html><head><meta charse ...

  4. 笔记 - ES6 - 学前浅析

    第01节:初识ES6 ● 兼容性:IE10+,Chrome,FireFox,NodeJS,移动端. ● 编译.转换: 1.在线转换:每次打开页面都需要转换: 2.提前编译:例如Babel. ● ES6 ...

  5. es6学习笔记8--Map数据结构

    Map Map结构的目的和基本用法 JavaScript的对象(Object),本质上是键值对的集合(Hash结构),但是只能用字符串当作键.这给它的使用带来了很大的限制. var data = {} ...

  6. 【全网最精简写法】ES6获取浏览器url跟参

    //ES6获取浏览器url跟参 public getUrlParam = a => (a = location.search.substr(1).match(new RegExp(`(^|&am ...

  7. ES6中的Promise详解

    Promise 在 JavaScript 中很早就有各种的开源实现,ES6 将其纳入了官方标准,提供了原生 api 支持,使用更加便捷. 定义 Promise 是一个对象,它用来标识 JavaScri ...

  8. ES6中export及export default的区别

    在ES6中,export和export default均可用于导出常量.函数.文件.模块等,你可以在其他文件或模块中通过import + (常量 | 函数 | 文件 | 模块)名的方式将其导入,以便能 ...

  9. ES6 你可能不知道的事 – 基础篇

    ES6 你可能不知道的事 – 基础篇 转载 作者:淘宝前端团队(FED)- 化辰 链接:taobaofed.org/blog/2016/07/22/es6-basics/ 序 ES6,或许应该叫 ES ...

最新文章

  1. zoomImg相册大图预览插件
  2. 三、6Gbps SAS冲锋队——Cheetah 15K.7、NS.2
  3. 关于锂离子法拉电容的短路实验
  4. 具备这四点品质的建站系统就爱了吧!
  5. Android组件之BroadCast简单实践
  6. OD的 CC断点,内存访问断点,硬件断点 解析
  7. Edge浏览器开发人员工具
  8. face 5k far landmark164 result
  9. ShardingSphere RAW JDBC 分布式事务XA 代码示例
  10. NPOI自定义单元格背景颜色
  11. 动态路由之RIP协议、Bellman-Ford算法
  12. Mapreduce中的分区Partitioner
  13. 17、手势(Gesture)
  14. 计算机毕业设计Java教材管理系统(源码+系统+mysql数据库+Lw文档)
  15. 卡密社区源码无加密完整版(php源码+mysql脚本)
  16. 微信小程序常见面试题及答案
  17. Halcon颜色分类-MLP
  18. 思科 计算机网络 第7章测试考试 答案
  19. 实训十二:交换机隔离VLAN配置
  20. 工业读写器行业解决方案

热门文章

  1. ChatGPT自动写了个AI办公office word插件,低配copilot,程序员看了焦虑。
  2. Xshell安装与使用
  3. 距离度量:欧氏距离,余弦距离,KL散度,马氏距离(含python代码实现)
  4. Metis异常检测初体验
  5. 谈谈反爬虫“政策与对策”
  6. C++调用两次析构函数原因
  7. java中给对象的List集合去重的几种方法(Lambda)
  8. pic16F877A音乐盒c语言,基于PIC16F877A单片机的混沌信号发生器的设计
  9. Excel·VBA自定义正则表达式函数、使用
  10. pandas将excel中多行多列单元格含有多个值拆分为一对一单行显示的方法(explode函数)