• JavaScript高级,ES6 笔记 第一天


    目录

    垃圾回收机制

    引用计数

    标记清除法

    闭包 

    变量提升

    动态参数和剩余参数

    展开运算符

     箭头函数(重要)

    this指向

    数组解构

     对象解构

     遍历数组forEach方法

    创建类

    子类继承:

    super调用父类函数


    垃圾回收机制

     

     其实最主要的主要是:

    全局变量不会自动回收,只会在页面关闭的时候回收,所以要少使用全局变量;

    局部变量会自动回收,使用完就会自动回收了

    引用计数

    实时的计算内存的引用次数,当其变为0时就销毁内存

     但是有缺点:嵌套引用会造成内存泄漏的问题:

    1. function fn(){
    2. let o1 = {}
    3. let o2 = {};
    4. o1.a = o2;
    5. o2.a = o1
    6. }
    7. fn();

     代码结束时,o2  o1都有被引用次数,所以使用引用计数不会销毁内存。所以现在的浏览器大多不采用这种方法。

    标记清除法

    闭包 

    例如:

    1. function fn(){
    2. let a = 1;
    3. function f2(){
    4. console.log(a);
    5. }
    6. f2()
    7. }
    8. fn()

     内层函数 f2 调用了外层函数变量 a 吗,这是最简单的写法

    最基础的写法为:

    闭包的最大作用是外部可以访问函数内部的变量!!

    1. function fn(){
    2. let a = 1;
    3. function f2(){
    4. return a
    5. }
    6. return f2
    7. }
    8. let sw = fn()()
    9. console.log(sw)//1

    也就是说函数fn的返回值为f2函数,所以fn()==f2,fn()()==f2()从而使得外部可以访问a

    应 用:使用变量a表示函数f2被调用的次数:

    1. function fn(){
    2. let a = 0;
    3. function f2(){
    4. a++
    5. console.log(a);
    6. }
    7. return f2
    8. }
    9. let sw = fn()
    10. sw()

    这样的好处是,a是函数内部的变量,外部不能直接修改这个值,只能通过f2得到,实现了数据私有

    变量提升

    这是js中的一种‘缺陷’,允许在变量声明之前被访问(存在于var)

    比如:

    1. console.log(num+'个');
    2. var num = 10

    结果为undefined个

    其本质为:

    1. var num
    2. console.log(num+'个');
    3. num = 10

    把所有的var声明的变量提升到当前作用域的最前面,但是只提升声明,不提升幅值

    let const没有变量提升的问题

    动态参数和剩余参数

    需求:求不定数量的数的和:

    1. function add(){
    2. let sum = 0;
    3. for(let i = 0;i<arguments.length;i++){
    4. sum+=arguments[i];
    5. }
    6. console.log(sum);
    7. }
    8. add(2,3,4,5,9)

    arguments就称为动态参数,将输入看成一个数组 (伪数组,不能用pop push等操作)

    第二种方法:

    1. function add(...args){
    2. let sum = 0;
    3. console.log(args);
    4. for(let i = 0;ilength;i++){
    5. sum+=args[i];
    6. }
    7. console.log(sum);
    8. }
    9. add(2,3,4,5,9)

    ...args就为剩余参数,也是将输入看成一个数组(真数组,可以使用pop等操作) ,但是其优点在于可以提取剩余变量,例如刚刚的那个例子,我再加一个需求:最少有两个参数:

    1. function add(a,...args){
    2. let sum = 0;
    3. console.log(args);
    4. for(let i = 0;ilength;i++){
    5. sum+=args[i];
    6. }
    7. console.log(sum);
    8. }
    9. add(2,3,4,5,9)

     这样的话,会把2给a  ,【3,4,5,9】给agrs,需要注意的是...args只能放最后。

    展开运算符

    作用:把数组展开:

    1. const arr = [2,3,4,6];
    2. console.log(...arr);//2 3 4 6

     经典应用为,得到数组的最大值(因为数组是不能直接使用math.max的):

    1. const arr = [2,3,4,6];
    2. console.log(Math.max(...arr));//6

    或者,合并数组:

    1. const arr = [2,3,4,6];
    2. console.log([3,4,...arr,99]);//[3, 4, 2, 3, 4, 6, 99]

     箭头函数(重要)

    主要作用是 使得代码更简洁,且改变this的指向

    基本形式:

    1. const fn = (x)=>{
    2. console.log(x);
    3. }
    4. fn(3)//3

      如果只有一个形参,可以忽略小括号:

    1. const fn = x=>{
    2. console.log(x);
    3. }
    4. fn(3)//3

     当函数只有一行代码时 可以省略大括号:

    1. const fn = x=>console.log(x);
    2. fn(3)//3

    如果是一行代码 且是return,可以省略:

    1. const fn = x=>x+x;
    2. console.log(fn(3));//6

     箭头函数没有arguments,只有...args:

    1. const fn = (...args)=>{
    2. let sum = 0;
    3. for(let i = 0;ilength;i++){
    4. sum+=args[i];
    5. }
    6. return sum
    7. }
    8. console.log(fn(3,4,5,7));//19

    this指向

    一般来说,this是谁调用函数 ,this指向谁

    但是箭头函数不会创造自己的this,而是从自己作用域的上一层沿用this,这个地方this是静态的,是函数声明时所在作用域下的this值

    1. let btn = document.querySelector('button');
    2. btn.addEventListener('click',function(){
    3. console.log(this);//btn
    4. })
    5. btn.addEventListener('click',()=>{
    6. console.log(this);//window
    7. })

    第一个的this 指向调用者btn 

    第二个this 指向的是箭头函数声明时的作用域,也就是上一个作用域,既window

    经典应用:需求是点击一个方块 一秒后背景颜色变红

    1. let divs = document.querySelector('.box')
    2. divs.addEventListener('click',function(){
    3. setTimeout(()=>{
    4. this.style.backgroundColor = 'red' //这个this还是指向divs
    5. },1000)
    6. })

     但是如果setTimeout里面的函数还是用function,那么this指向的是window,因为是window调用了setTimeout

    数组解构

    数组解构是将数组的单元值快速批量赋值给变量的方法

    1. const arr = [123,22,33]
    2. const[max,min,avr] = arr;
    3. console.log(max);//123

     应用:变量值交换

    1. let a = 1;
    2. let b = 2;
    3. [a,b]=[b,a]
    4. console.log(a);//2
    5. console.log(b);//1

     变量多 单元值少的情况

    1. const[a,b,c,d] = [1,2,3]
    2. console.log(a,b,c,d);//1 2 3 undefined

      变量少 单元值多的情况

    1. const[a,b] = [1,2,3]
    2. console.log(a,b);//1 2

     对象解构

    1. const person = {
    2. name :'aa',
    3. age:17
    4. }
    5. const{name,age} = person;
    6. console.log(name);//aa
    7. console.log(age);//17

     可以改名:

    1. const person = {
    2. name :'aa',
    3. age:17
    4. }
    5. const{name:username,age} = person;
    6. console.log(username);//aa
    7. console.log(age);//17

     多重对象解构:

    1. const pig = {
    2. name: 'aa',
    3. family:{
    4. mom :'bb',
    5. papa:'cc',
    6. sist:'dd'
    7. },
    8. age:18
    9. }
    10. const {name,family:{mom,papa,sist}}=pig;
    11. console.log(mom);//bb

     遍历数组forEach方法

    1. const arr = [11,22,33];
    2. arr.forEach(function(item,index){
    3. console.log(item);
    4. console.log(index);
    5. })

    结果为:11 0 22 1 33 2

    item必须要写  index可以不写

     贴一个小案例 可以看一下

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>商品渲染title>
    8. <style>
    9. * {
    10. margin: 0;
    11. padding: 0;
    12. box-sizing: border-box;
    13. }
    14. .list {
    15. width: 990px;
    16. margin: 0 auto;
    17. display: flex;
    18. flex-wrap: wrap;
    19. }
    20. .item {
    21. width: 240px;
    22. margin-left: 10px;
    23. padding: 20px 30px;
    24. transition: all .5s;
    25. margin-bottom: 20px;
    26. }
    27. .item:nth-child(4n) {
    28. margin-left: 0;
    29. }
    30. .item:hover {
    31. box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
    32. transform: translate3d(0, -4px, 0);
    33. cursor: pointer;
    34. }
    35. .item img {
    36. width: 100%;
    37. }
    38. .item .name {
    39. font-size: 18px;
    40. margin-bottom: 10px;
    41. color: #666;
    42. }
    43. .item .price {
    44. font-size: 22px;
    45. color: firebrick;
    46. }
    47. .item .price::before {
    48. content: "¥";
    49. font-size: 14px;
    50. }
    51. .filter {
    52. display: flex;
    53. width: 990px;
    54. margin: 0 auto;
    55. padding: 50px 30px;
    56. }
    57. .filter a {
    58. padding: 10px 20px;
    59. background: #f5f5f5;
    60. color: #666;
    61. text-decoration: none;
    62. margin-right: 20px;
    63. }
    64. .filter a:active,
    65. .filter a:focus {
    66. background: #05943c;
    67. color: #fff;
    68. }
    69. style>
    70. head>
    71. <body>
    72. <div class="filter">
    73. <a data-index="1" href="javascript:;">0-100元a>
    74. <a data-index="2" href="javascript:;">100-300元a>
    75. <a data-index="3" href="javascript:;">300元以上a>
    76. <a href="javascript:;">全部区间a>
    77. div>
    78. <div class="list">
    79. div>
    80. <script>
    81. const goodsList = [
    82. {
    83. id: '4001172',
    84. name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',
    85. price: '289.00',
    86. picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',
    87. },
    88. {
    89. id: '4001594',
    90. name: '日式黑陶功夫茶组双侧把茶具礼盒装',
    91. price: '288.00',
    92. picture: 'https://yanxuan-item.nosdn.127.net/3346b7b92f9563c7a7e24c7ead883f18.jpg',
    93. },
    94. {
    95. id: '4001009',
    96. name: '竹制干泡茶盘正方形沥水茶台品茶盘',
    97. price: '109.00',
    98. picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',
    99. },
    100. {
    101. id: '4001874',
    102. name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',
    103. price: '488.00',
    104. picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',
    105. },
    106. {
    107. id: '4001649',
    108. name: '大师监制龙泉青瓷茶叶罐',
    109. price: '139.00',
    110. picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',
    111. },
    112. {
    113. id: '3997185',
    114. name: '与众不同的口感汝瓷白酒杯套组1壶4杯',
    115. price: '108.00',
    116. picture: 'https://yanxuan-item.nosdn.127.net/8e21c794dfd3a4e8573273ddae50bce2.jpg',
    117. },
    118. {
    119. id: '3997403',
    120. name: '手工吹制更厚实白酒杯壶套装6壶6杯',
    121. price: '99.00',
    122. picture: 'https://yanxuan-item.nosdn.127.net/af2371a65f60bce152a61fc22745ff3f.jpg',
    123. },
    124. {
    125. id: '3998274',
    126. name: '德国百年工艺高端水晶玻璃红酒杯2支装',
    127. price: '139.00',
    128. picture: 'https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg',
    129. },
    130. ]
    131. let list = document.querySelector('.list');
    132. function get(arr) {
    133. let str = ``
    134. arr.forEach((item, index) => {
    135. let { id, name, price, picture } = item;
    136. str += `
      ${id}>
    137. ${picture} alt="">
    138. ${name}

    139. ${price}

    140. `
  • });
  • list.innerHTML = str;
  • }
  • get(goodsList)
  • let filter = document.querySelector('.filter').querySelectorAll('a');
  • for(let i=0;ilength;i++){
  • filter[i].addEventListener('click',function(){
  • if(this.getAttribute('data-index')==1){
  • arr = goodsList.filter(item => item.price > 0 && item.price <= 100)
  • }
  • else if(this.getAttribute('data-index')==2){
  • arr = goodsList.filter(item => item.price > 100 && item.price <= 300)
  • }
  • else if(this.getAttribute('data-index')==3){
  • arr = goodsList.filter(item => item.price > 300)
  • }
  • else{
  • arr = goodsList;
  • }
  • get(arr)
  • })
  • }
  • script>
  • body>
  • html>
  • 创建类

    需要使用constructor函数来声明参数

    1. class fa{
    2. constructor(x,y){
    3. this.x = x;
    4. this.y = y;
    5. }
    6. sum(){
    7. console.log(this.x+this.y);
    8. }
    9. }
    10. let a = new fa()

    子类继承:

    利用extends

    1. class fa{
    2. constructor(x,y){
    3. this.x = x;
    4. this.y = y;
    5. }
    6. sum(){
    7. console.log('hhhh');
    8. }
    9. }
    10. class son extends fa{}
    11. let b = new son()
    12. b.sum()//hhhh

    super调用父类函数

    如果想将子类的参数传到父类并调用父类的函数,需要使用super方法,主要就是可以将子类的参数传给父类

    1. class fa{
    2. constructor(x,y){
    3. this.x = x;
    4. this.y = y;
    5. }
    6. sum(){
    7. console.log(this.x + this.y);;
    8. }
    9. }
    10. class son extends fa{
    11. constructor(x,y){
    12. super(x,y)
    13. }
    14. }
    15. let a = new son(7,4)
    16. a.sum()//11

    如果子类本身也有参数和函数,也可以声明super,但是需要注意的是,super必须在this之前

    1. class fa{
    2. constructor(x,y){
    3. this.x = x;
    4. this.y = y;
    5. }
    6. sum(){
    7. console.log(this.x + this.y);
    8. }
    9. }
    10. class son extends fa{
    11. constructor(x,y){
    12. super(x,y)
    13. this.x = x;
    14. this.y = y;
    15. }
    16. jian(){
    17. console.log(this.x - this.y);
    18. }
    19. }
    20. let a = new son(7,4)
    21. a.jian()//3
    22. a.sum()//11

  • 相关阅读:
    教材管理系统设计与实现
    Redis基础(一)
    JVS-rules中的基础与复合变量:规则引擎的心脏
    对于Oracle,MySQL,SQL Server重复数据删除
    DMRS的产生
    SpringBoot中@AutoWired注解的静态变量
    【万字长文】说说电商系统常见的 9 个大坑,人麻了……
    KBU1510-ASEMI整流桥KBU1510
    思科Etherchannel
    文献学习-38-用于增量组织病理学分类的内存高效提示调整
  • 原文地址:https://blog.csdn.net/qq_54517101/article/details/126681391