金子fa

导航

js数组.es5与es6总结

数组

数组定义

var arr = []

这是一个空数组,定义带数据的数组:

var arr = ['张三','李四','王五','赵六']

输出结果:

数组中的数据类型没有限制,在实际项目中,数组中通常会存储同一类型的数据。

var arr = ['a',2,false,undefined,{name:"张三"}];

数组这种数据,相当于在一个大空间中,有很多小空间,每个值前面的数字,表示这个小空间的编号,专业术语叫下标。第一个下标永远是0,依次向后递增,最后一个下标是值的个数-1

也就是说,数组这种数据中每个值是有顺序的。

js还提供了一个构造函数,用来创建数组:

var arr = new Array("张三","李四","王五")

这两种方式定义的数据是一样的。

有一种情况,这两种定义方式是不一样的:

var arr = [5]
var brr = new Array(5)
console.log(arr,brr)

[]形式定义的是一个数组中有一个小空间,其中的值是5;构造函数方式定义的,表示有5个空的小空间。

数组的规律:

第一个值的下标永远是0;

最后一个值的下标永远是值的个数-1。

数组基本操作

数组中值的个数:数组.length

var arr = ['张三',"李四","王五","赵六"];
var arr1 = [1,2,3,4,5,6];
console.log(arr.length); // 4
console.log(arr1.length); // 6

访问数组中的元素:数组[下标]

例:

var arr = ["张三","李四","王五"];
console.log(arr[1]); // 李四

第一个值永远是:数组[0];最后一个值永远是:数组[数组.length-1]

添加元素:数组[下标] = 值

例:

var arr = ["张三","李四"];
arr[2] = "王五";
console.log(arr); // (3) ["张三", "李四", "王五"]
arr[10] = "赵六";
console.log(arr); // (11) ["张三", "李四", "王五", empty × 7, "赵六"] 中间还有7个空元素

修改元素:数组[下标] = 值

例:

var arr = ["张三","李四"];
arr[0] = "王五";
console.log(arr); // (2) ["王五", "李四"]

使用说明:如果下标是已经存在的,那赋值操作就是修改数组元素的值,如果下标是不存在,那赋值操作就给数组添加元素。

删除元素:delete 数组[下标]

var arr = [1,2,3];
delete arr[0];
console.log(arr)

这种删除方式,只能删除值,并不能删除小空间。

数组长度的赋值:

var arr = [1,2,3];
arr.length = 0;
console.log(arr) // []

var arr = [1,2,3];
arr.length = 10;
console.log(arr)
var arr = [1,2,3];
arr.length = 1;
console.log(arr) // [1]

遍历数组:

如果要将数组中的所有元素都输出,操作如下:

var arr = ["张三","李四","王五","赵六"];
console.log(arr[0]); // 张三
console.log(arr[1]); // 李四
console.log(arr[2]); // 王五
console.log(arr[3]); // 赵六

从上面输出的代码中可以看出,多次输出是在进行重复动作,并且多次重复之间是有规律可循的,所以可以使用循环进行这个重复动作:

var arr = ["张三","李四","王五","赵六"];
var length = arr.length;
for(var i=0;i<length;i++){
console.log(arr[i]);
}

结果:

 
 

这种使用循环将数组中每个元素输出的操作叫做数组的遍历 - 每个元素都经历一次

遍历对象的for in语法也可以遍历数组:

var arr = ["张三","李四","王五","赵六"];
for(var i in arr){
console.log(arr[i]);
}

 

两种遍历方式有区别:

var arr = ['a','b','c'];
arr[5] = 'd'
console.log(arr);
for(var i=0;i<arr.length;i++){
   console.log(arr[i]);
}

 

空的空间会遍历出undefined

var arr = ['a','b','c'];
arr[5] = 'd'
console.log(arr);
for(var i in arr){
   console.log(arr[i]);
}

 

空的空间不会被遍历。

var arr = ['a','b','c'];
for(var i=0;i<arr.length;i++){
   console.log(i);
}


下标是数字。

var arr = ['a','b','c'];
for(var i in arr){
   console.log(i);
}

 

下标是字符串。所以for in的语法更适合遍历对象,为了避免不必要的错误,尽量不要用这种语法来遍历数组。

数组练习:

  1. 利用for循环求数字数组中所有元素的和

    var arr = [10,20,30,40,50];
    var sum = 0;
    for(var i = 0;i < arr.length; i++){
    sum += arr[i];
    }
    console.log(sum);
  2. 有一个数组,具体内容如下:

    var arr = [
       "越南被曝咖啡造假:咖啡粉里掺加电池芯",
       "抗日神剧被当教材:机密文件居然有女优名字",
       "王俊凯任联合国大使:系最年轻的联合国大使",
       "行人闯红灯遭水喷 目前还在测试阶段",
       "68条鱼估价超600万 什么鱼要这么贵?"
    ]

    利用循环使用js做出如下图效果:

     

    var arr = [
       "越南被曝咖啡造假:咖啡粉里掺加电池芯",
       "抗日神剧被当教材:机密文件居然有女优名字",
       "王俊凯任联合国大使:系最年轻的联合国大使",
       "行人闯红灯遭水喷 目前还在测试阶段",
       "68条鱼估价超600万 什么鱼要这么贵?"
    ];
    document.write("<ul>");
    for(var i=0;i<arr.length;i++){
    document.write("<li>"+arr[i]+"</li>");
    }
    document.write("</ul>")
  3. 求数组中的最大值

    var arr = [1,9,3,6,8,5,4,7,2,12];
    // 求出最大值
    var length = arr.length;
    var max = arr[0];
    for(var i=1;i<length;i++){
       if(max<arr[i]){
           max = arr[i];
      }
    }
    console.log(max);
  4. 把1~100这个100个数字存到数组中

    var arr = [];
    for(var i=1;i<=100;i++){
       arr[arr.length] = i
    }
  5. 整理数组数据,模拟京东的商品列表

     

    <script>
       var arr = [
      {
           goodsImg:'https://img30.360buyimg.com/seckillcms/s140x140_jfs/t1/186995/37/12433/183771/60e7ffb3E1b78db87/c5696abfd650ef64.jpg.webp',
           goodsname:'荣耀畅玩20 手机 老人机 学生智能机 【咨询加赠华为原装Type-C线】 幻夜黑 全网通(6G+128G)',
           goodsoldprice:'1399',
           goodsnowproce:'1029'
      },
      {
           goodsImg:'https://img20.360buyimg.com/seckillcms/s140x140_jfs/t1/116335/26/233/214256/5e8998c4E3b5fc871/ec122a9622175d7e.jpg.webp',
           goodsname:'【纯银999十二生肖七彩建盏】【配银饰鉴定证+礼盒+礼盒袋+收藏证书】天目釉原矿铁胎茶盏主人杯茶具茶 纯手工七彩盏-莲花纯银999',
           goodsoldprice:'659',
           goodsnowproce:'199'
      },
      {
           goodsImg:'https://img12.360buyimg.com/seckillcms/s140x140_jfs/t1/182318/5/13135/123400/60e55430E14b60a71/070af11351a8de90.jpg.webp',
           goodsname:'风味坐标 手撕牛肉干 400g(经典原味) 内蒙古锡林浩特特产 高蛋白休闲零食',
           goodsoldprice:'229',
           goodsnowproce:'69'
      },
      {
           goodsImg:'https://img11.360buyimg.com/seckillcms/s140x140_jfs/t1/185818/10/12878/72765/60e41060Ed9ebc1a3/5fa7730180a53328.jpg.webp',
           goodsname:'蔬果园蓝风铃香水洗衣液除菌液母婴可用持久留香酵素英式香氛香味洗衣液洁净家庭组合套装 蓝风铃2kg*3+500g*5袋+留香珠18g*2',
           goodsoldprice:'159',
           goodsnowproce:'119'
      },
    ];
    // 遍历数组,输出标签
    for(var i=0;i<arr.length;i++){
       document.write('<li>');
       document.write('<img src="'   +  arr[i].goodsImg  +   '">');
       document.write('<h4>'+arr[i].goodsname+'</h4>');
       document.write('<b>'+arr[i].goodsnowproce+'</b>');
       document.write('<span>'+arr[i].goodsoldprice+'</span>');
       document.write('</li>');
    }
    </script>
    <style>
    li{
       list-style-type: none;
       padding: 0;
       margin: 0;
       width: 140px;
       height: 190px;
       border:1px solid #000;
       float:left;
       margin:0 10px;
    }
    li h4{
       width: 140px;
       white-space: nowrap;
       overflow: hidden;
       text-overflow: ellipsis;
       padding: 0;
       margin: 0;
    }
    </style>

数组嵌套

数组中的值类型是没有限制的,所以数组中也可以存储数组。

var arr = [
"Jack",
"Rose",
["王宝强","马蓉"],
["贾乃亮","李小璐"]
];
console.log(arr);
console.log(arr[2]);
console.log(arr[2][1]);

效果:

 
 

包含数组的数组,叫做多维数组,我们用的最多的就是二维数组。

var arr = [
   '王宝强',
   '贾乃亮',
  [
       '岳云鹏',
       '陈伟霆',
       '刘诗诗',
      [
           '刘德华',
          [
               '张艺兴',
               '周笔畅'
          ]
      ]
  ]
];
var brr = arr[2]
console.log(brr); // ['岳云鹏', '陈伟霆','刘诗诗',[ '刘德华',[ '张艺兴','周笔畅' ]]]

var crr = brr[3]
console.log(crr); // [ '刘德华',[ '张艺兴','周笔畅' ]]

var drr = crr[1]
console.log(drr); // [ '张艺兴','周笔畅' ]

var z = drr[1]
console.log(z); // 周笔畅

var zz = arr[2][3][1][1]
console.log(zz); // 周笔畅

基础类型和引用类型

js中允许出现的数据:number、string、boolean、null、undefined、{}、[]、function

根据不同类型的数据存储方式以及赋值方式的不同,我们将数据分为两类:基本类型和引用类型。

基础数据类型:number、string、boolean、undefined、null

引用数据类型:[]、function, {}

基础类型和引用类型的区别:

  1. 存储方式不同

    基础类型将值存在栈内存中;引用类型将值存在堆内存中,将堆内存的内存地址存在栈中。

    var a = 1;
    var obj = {name:"张三",age:12}

     

  2. 赋值过程不同

    基础类型赋值时,将值复制给另一个变量;引用类型赋值时,将栈中的地址复制给别的变量。

    var a = 1
    var b = a;
    a = 2;
    console.log(b) // 2

     

    复制值以后,修改其中一个,另一个不会受到影响。

    var arr = ['a','b','c'];
    var brr = arr;
    arr[0] = 'd'
    console.log(brr) // ['d','b','c'];

     

    当改变其中一个变量中的值,另一个变量中的值也会发生改变。

  3. 全等的比较规则不同

    基础类型全等比较的时候,比较类型和值;

    var a = 1;
    var b = 1;
    console.log(a === b)

    引用类型全等比较的时候比较栈中存的内存地址是否相同。

    var arr = [1,2,3];
    var brr = [1,2,3]
    console.log(arr === brr)

数组方法

如何给数组的开头添加一个元素?

var arr = ['a','b','c']
for(var i=arr.length-1;i>=0;i++){
   arr[i+1] = arr[i]
}
arr[0] = 'd'
console.log(arr)

这样操作起来比较复杂。为了方便我们对数组进行操作,js提供了一些方法,可以快速的操作数组:

  • unshift - 给数组开头添加一个或多个元素 - 返回数组新长度

    var arr = ['a','b','c'];
    var l = arr.unshift('d')
    console.log(arr) // ['d','a','b','c']
    console.log(l) // 4
  • push - 给数组的末尾添加一个或多个元素 - 返回数组新长度

    var arr = ['a','b','c'];
    var l = arr.push('d')
    console.log(arr) // ['a','b','c','d']
    console.log(l) // 4
  • shift - 删除数组的第一个元素 - 返回被删掉的元素

    var arr = ['a','b','c'];
    var ele = arr.shift()
    console.log(arr) // ['b','c']
    console.log(ele) // 'a'
  • pop - 删除数组最后一个元素 - 返回被删掉的元素

  var arr = ['a','b','c'];
 var ele = arr.pop()
 console.log(arr) // ['a','b']
 console.log(ele) // 'c'
  • splice - 对数组做增、删、改的操作

    var arr = ['a','b','c']
    // 改 - 参数1:开始下标;参数2:删除的个数;参数3:在删除的位置放上的新的元素 - 可以是多个
    arr.splice(1,1,'d') // ['a','d','c']
    // 增
    arr.splice(1,0,'d') // ['a','d','b','c'] - 删除0个,就是不删除,然后放上新元素
    // 删 - 第三个参数可以省略
    arr.splice(1,0) // ['a','c']
  • concat - 数组的拼接

    var arr = ['a','b','c'];
    var brr = ['d','e','f'];
    // 将arr和brr合成一个更大的数组
    var crr = arr.concat(brr) // ['a','b','c','d','e','f']
    // 将一个或多个值和数组合并成一个大数组
    var crr = arr.concat(1,2,3)// ['a','b','c',1,2,3]
  • sort - 数组的排序

    var arr = [9,5,3,7,1,6,4,8,2];
    arr.sort() // 默认升序
    console.log(arr) // [1,2,3,4,5,6,7,8,9]
    arr.sort(function(a,b){ // a代表前面的数,b代表后面的数
       return a-b; // 升序 - 如果前面的数-后面的数>0,则交换位置
       return b-a; // 降序 - 如果后面的数-前面的数>0,则交换位置
    })
  • reverse - 数组的反转

    var arr = ['a','b','c'];
    arr.reverse()
    console.log(arr) // ['c','b','a']
  • join - 将数组中的元素使用指定的连接符连接在一起

    var arr = ['a','b','c'];
    var str = arr.join('_') // 参数是连接符
    console.log(str) // a_b_c

    var str = arr.join() // 默认使用逗号连接
    console.log(str) // a,b,c

    var str = arr.join('')
    console.log(str) // abc
  • slice - 截取数组

    var arr = ['a','b','c','d','e','f'];
    // 将数组中的 'b','c','d'截取出来,组成新的数组
    var brr = arr.slice(1,4) // 参数1是开始截取的下标,参数2是截取的结束下标,结果中不包含结束下标对应的元素
    console.log(brr) // ['b','c','d']
    // 如果省略第2个参数,默认从开始下标截取到数组末尾
    var crr = arr.slice(1)
    console.log(crr) // ['b','c','d','e','f']

冒泡排序

相邻两个元素进行比较,将一个数组中的数字使用循环进行升序或降序的排列

 

var arr = [3,2,1]; // ---> [1,2,3]
// 相邻的元素比较,就是下标i的元素跟下标i+1的元素比较 - 所以循环要比正常的遍历少一次
for(var i=0;i<arr.length-1;i++){
   // 如果前面的元素比后面的元素大
   if(arr[i]>arr[i+1]){
  // 则交换位置
       var tmp = arr[i]
       arr[i] = arr[i+1]
arr[i+1] = tmp
  }
}
// 这个循环结束后,arr变为:[2,1,3]
// 所以需要继续排列
for(var i=0;i<arr.length-1;i++){
   // 如果前面的元素比后面的元素大
   if(arr[i]>arr[i+1]){
  // 则交换位置
       var tmp = arr[i]
       arr[i] = arr[i+1]
arr[i+1] = tmp
  }
}
// 这个循环结束后,arr变为:[1,2,3]
// 两个循环代码是重复的,所以用循环处理。3个元素循环两次,4个元素循环3次,所以循环重复的次数也是数组长度-1
for(var j=0;j<arr.length-1;j++){
   for(var i=0;i<arr.length;i++){
       if(arr[i]>arr[i+1]){
      var tmp = arr[i]
           arr[i] = arr[i+1]
           arr[i+1] = tmp
      }
  }
}
// 如果要降序排序,就将判断条件中的>改为<即可

选择排序

降序:先找最大值,排在最左边,再找第二大的值,往左边靠...,已经排好的,不再参与比较

 

var arr = [3,2,1]; // ---》 [1,2,3]
// arr[0]放最小的值,所以将arr[0]跟后面所有值比较,如果有比arr[0]更小的,就跟arr[0]交换位置
for(var i=1;i<arr.length;i++){
   if(arr[0]>arr[i]){
  var tmp = arr[0]
       arr[0] = arr[i]
       arr[i] = tmp
  }
}
// 此时的数组:[1,3,2]
// 第1个位置的数字排好了,排第2个位置上的数字
// arr[1]放剩下的数字中最小的,使用arr[1]跟后面的数字比较,如果有比arr[1]更小的,就跟arr[1]交换位置
for(var i=2;i<arr.length;i++){
   if(arr[1]>arr[i]){
  var tmp = arr[1]
       arr[1] = arr[i]
       arr[i] = tmp
  }
}
// 此时的数组:[1,2,3]
// 重复代码用循环处理,3个数排2次,4个数排3次
for(var j=0;j<arr.length-1;j++){
   for(var i=j+1;i<arr.length;i++){
       if(arr[j]>arr[i]){
      var tmp = arr[j]
           arr[j] = arr[i]
           arr[i] = tmp
      }
  }
}
// 如果要进行降序排列,就将判断条件中的>换成<即可


 

 

 

 

 

 数组概念:

 

 

 

 

 

 {}与object区别

 

 

 数组定义

 

 

 数组array

数组细节

 

 

 5、当使用【】定义数据时,如果【】中只有一个数据时,此时代表大空间中只有一个数据是这个数字;当使用new array()定义数据是,如果()中只有一个数字,表示大空间的小空间

 

 

 数组操作

 

 

 

 

 

 下标=索引

 

 

 

 

 

 

 

 

 

 

 

 

 

 数组的遍历

 

 

 

 

 

 

 

 

 

 使用循环处理重复 - 利用循环遍历数组

倒着循环

 

 

 对象遍历与数组的遍历

 

 

 区别2

 

 

 

 

 

 建议大家使用i=0的方式遍历

 

 obj显示的数据是自己定义的键

 

 

数组练习

 

 

 

 

 

 重要

 

 

 遍历是为了验证假设成立

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 通过数组渲染京东商品案例

 

 

 

 

 

 等量代替

数组嵌套

 

 

 

 

 

 

 

 

 

 基础类型和引用类型

 

 

 

 

 

 

 

 

 

 

 

 比较

 

 

 基础类型会将数据存储在栈中

 

 

 

数组方法

 

 

 

 

 

 

 

 

 

 

 

 

考试错题

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 只要是具体的值就能是实参

常量和变量

 

 

 

 

es5

 

ES5的语法

 

js在产生的时候,年代比较早,当时的web需求比较少,所以刚开始的js功能比较少,语法没有特别严谨。随着时代的发展和web应用的普及,js需要更多的功能,以及更严谨的语法,所以,js会有版本的升级。第一版的js是ECMA一开始统一了标准以后的版本。我们现在的所使用的语法,大多是ECMAScript版本3的语法,简称es3。到目前为止,已经有了es7,8,9,甚至es10 的版本了。近几年,基本每年都会有新的版本更新。

 

每个版本的更新,都需要浏览器支持才能运行,但浏览器不会在js更新之后,立马更新。所以有的版本出来之后,需要在很长时间之后,浏览器才会兼容他。到目前为止,我们公认,es5是兼容性最好的版本。

 

es5比起我们所正在使用的es3,语法没有什么变化,增加了一个严格模式,还有一些数组的方法。

 

严格模式

 

由于js的作用域和隐式声明变量等语法会造成很多预想不到的错误,所以ES5中新增了一个严格模式的语法,用于严格规范代码的书写。

 

使用语法:

 

"use strict";

 

使用说明:

 

  1. 要放在代码的最前面,也就是在script标签中的第一行或者某个函数中的第一行,否则会失效

  2. 严格模式可以规范当前script标签或者当前函数中的代码,不能规范别的script标签中的代码和别的函数

 

规范的语法:

 

  1. 不允许隐式声明变量

  2. 禁止函数中的形参重名

  3. 禁止函数中的this代表window

 

为什么要使用严格模式?

 

  1. 可以让代码更加规范

  2. 可以让代码运行起来更快,提高运行效率

 

新增数组方法

 

indexOf方法

 

查找某个元素在数组中第一次出现的位置

 

语法:

 

arr.indexOf(元素,[开始查找的起始下标]);
# 参数1:将要查找的元素
# 参数2:可选项。从哪个下标开始往后查找
# 返回值:如果找到了,就返回这个元素在数组中的下标,如果没有找到,就返回-1

 

例:

 

var arr = [1,3,5,7,7,5,3,1];
console.log(arr.indexOf(5)); // 2 - 查找数字5在数组中第一次出现的下标
console.log(arr.lastIndexOf(5)); // 5 - 查找数字5在数组中最后一次出现的位置
console.log(arr.indexOf(5,3)); // 5 - 从下标2开始查找数字5在数组中第一次出现的位置
console.log(arr.lastIndexOf(5,4)); // 2 - 从下标4开始查找数字5在数组中最后一次出现的下标
console.log(arr.indexOf("5")); // -1 - 数组中全是数字,找不到字符串5,所以返回-1

 

forEach方法

 

用于遍历数组

 

语法:

 

arr.forEach(function(值, 下标, 当前数组){
// 代码段
});
# 在这个方法中需要传入一个函数参数,这个函数的参数说明如下:
# 参数1:数组遍历出来的每个值
# 参数2:可选项。数组遍历出来的每个值对应的下标
# 参数3:可选项。被遍历的当前数组

 

例:

 

var arr = [1, 2, 3, 4, 5];
arr.forEach(function(x, index, a){
console.log(x + '|' + index + '|' + (a === arr));
});
// 输出为:
// 1|0|true
// 2|1|true
// 3|2|true
// 4|3|true
// 5|4|true

 

使用说明:

 

这个方法没有返回值,返回值为undefined,不会改变原来数组的值。

 

map方法

 

遍历数组,并将每个元素经过函数处理后,形成新的元素,所有新元素组成新数组返回

 

语法:

 

arr.map(function(值,下标,当前数组){
return 新的值 - 通常新的值是由旧的值处理以后得到
});

 

例:

 

var arr = [1, 2, 3, 4, 5];
var arr2 = arr.map(function(item){
return item*item;
});
console.log(arr2); //[1, 4, 9, 16, 25]

 

使用说明:

 

这个方法主要用于以同样的规则处理数组中的每个值,并组成新的数组返回

 

filter方法

 

将数组中满足指定条件的值,组成新的数组返回

 

语法:

 

arr.filter(function(值, 下标, 当前数组){
return 筛选条件
});

 

例:

 

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var arr2 = arr.filter(function(v, index) {
return v>5
});
console.log(arr2); //[6, 7, 8, 9, 10]

 

使用说明:

 

使用方法和功能跟map方法很像,只是运行规则不一样。map方法中的函数,用于返回新的元素,而filter方法中的函数,根据返回true或false来筛选元素

 

字符串

 

字符串的重新认识

 

字符串定义:

 

var str = '';
var str = "";
var str = new String()

 

这三种定义方式没有区别。

 

字符串中字符的个数:字符串.length

 

字符串中获取某个字符的时候,可以根据下标来获取:

 

var str = "abcdef";
var s = str[1]
console.log(s) // 'b'
var s1 = str[0]
console.log(s1) // 'a'

 

所以字符串也是可以进行遍历的:

 

var str = "abcdef";
for(var i=0;i<str.length;i++){
   console.log(str[i],i)
}

 

那字符串是否也可以像数组一样,通过下标更改其中的某个字符呢?

 

var str = 'abcdef';
str[str.length] = 'g'

str[0] = 'g'
console.log(str) // abcdef

 

操作后,字符串并没有新增和更改。

 

因为字符串是只读数据,只能读,不能增删改。

 

字符串可以进行比较,我们在前面的时候,有过这样的比较:

 

console.log('12'>'5') // false
console.log('12'<'5') // true

 

字符串可以比较,但是规则跟数字比较是不一样的。

 

字符串比较的规则是逐字符进行比较,大小由阿斯克码来决定。

 

阿斯克码

 

计算机内部只能识别2进制数据,不能识别字母等字符。

 

为了能让计算机识别字符,科学家制定了一个对照表,当输入一段2进制指令的时候,就能显示成某个字符。

 

这个对照表叫做阿斯克码表,其中包含了128个常用字符跟2进制的对照关系。

 

 
 

 

通过阿斯克码表,我们可以得出一些字符串比较的规律:

 

  1. 字母比数字大

  2. 小写字母比大写字母大

  3. 字母越靠后越大

 

字符串能比较大小,中文汉字也是字符串,中文汉字也能比较大小:

 

console.log('我'>'你') // true
console.log('你'>'我') // false

 

中文汉字的大小由unicode来决定。

 

阿斯克码总共128个,包含符号、大小写英文字母、数字。阿斯克码是由美国人创建的,所以对于英文的支持非常好。后来随着计算机的普及,各个国家在使用计算机的时候,没办法使用本国文字,这样用起来非常困难。所以众多国家的科学家一起制定了一个更大的对照表,包含各个国家的文字符号,所以称之为万国码,也叫作unicode。

 

其实unicode就是更大的阿斯克码。

 

字符串方法

 

  • charCodeAt - 根据指定下标获取对应的字符的阿斯克码

    var str = 'abcdef';
    // 获取下标为3的字符的阿斯克码
    var res = str.charCodeAt(0); // 参数为指定的下标
    console.log(res); // 97
  • String.fromCharCode - 根据指定的阿斯克码得到对应的字符

    // 获取98对应的字符
    var res = String.fromCharCode(98); // 参数为指定的阿斯克码
    console.log(res); // b
  • indexOf - 查找字符或子字符串在大字符串中第一次出现的位置

    var str = 'i love you';
    // 找到o字符在str中第一次出现的位置
    var s = str.indexOf('o'); // 参数为要查找的字符
    console.log(s); // 3

    var s = str.indexOf('o',4); // 参数2为开始查找的下标
    console.log(s) // 8

    var s = str.indexOf('a') // 查找a字符在字符串中第一次出现的下标
    console.log(s) // -1 - 找不到就返回-1
  • lastIndexOf - 查找字符在字符串中最后一次出现的下标

    var str = 'i love you';
    // 找到o字符在str中最后一次出现的位置
    var s = str.lastIndexOf('o');
    console.log(s); // 8

    var s = str.lastIndexOf('o',7) // 将下标7当做字符串末尾,查找字符o在字符串中最后一次出现的下标
    console.log(s) // 3

    var s = str.lastIndexOf('a')
    console.log(s) // -1 - 找不到就返回-1
  • slice - 截取字符串

    var str = 'abcdef';
    // 从下标1截取到下标4
    var s = str.slice(1,4) // 参数1是开始截取的下标,参数2是截取的结束下标
    console.log(s) // bcd - 结果中不包含结束下标对应的字符

    var s = str.slice(1) // 省略第二个参数,默认能截取到字符串末尾
    console.log(s) // bcdef

    var s = str.slice(-3,-1) // 下标可以使用负数表示,-3表示倒数第3个字符,-1表示倒数第1个字符
    console.log(s) // def

    var s = str.slice(-1,-3) // 如果开始下标比结束下标大,会截取到空
    console.log(s) // ''
  • split - 将字符串使用指定的分隔符分割为数组

    var str = 'a-b-c-d';
    var arr = str.split('-') // 参数为分隔符,使用-将字符串分割为一个数组
    console.log(arr) // ['a','b','c','d']

    var arr = str.split('-',3) // 参数2表示数组中要保留前几个元素
    console.log(arr) // ['a','b','c']

    var str = 'abcd';
    var arr = str.split() // 省略了分隔符,默认就不分割,将整个字符串当做一个元素放在数组中
    console.log(arr) // ['abcd']

    var arr = str.split('')
    console.log(arr) // ["a", "b", "c", "d"]
  • replace - 使用新字符串将字符串中某一部分替换掉

    var str = '你的头发还好吗?';
    str = str.replace('头发','眉毛') // 参数1是被替换的字符串中的部分,参数2是新内容
    console.log(str) // '你的眉毛还好吗?'

    str = str.replace('','哈哈') // 参数1为空,就会将新内容添加到原字符串的最前面
    console.log(str) // '哈哈你的眉毛还好吗?'
  • trim - 去除字符串两端空白

    var str = '    aaa          ';
    str = str.trim()
    console.log(str) // 'aaa' - 左右两端的空白被去掉了

    str = str.trimLeft() // 去除左边的空白
    console.log(str) // 'aaa         '

    str = str.trimRight() // 去除右边的空白
    console.log(str) // '   aaa'
  • toUpperCase - 将字符串中字母转为大写

    var str = 'i love you';
    str = str.toUpperCase()
    console.log(str) // 'I LOVE YOU'
  • toLowerCase - 将字符串中字母转为小写

    var str = 'I LOVE YOU';
    str = str.toLowerCase()
    console.log(str) // 'i love you'
  • substr - 截取字符串

    var str = 'abcdef';
    str = str.substr(1,3) // 参数1是开始截取的下标,参数2是截取的字符串长度
    console.log(str) // bcd

    str = str.substr(1) // 省略参数2默认截取到字符串末尾
    console.log(str) // bcdef

    str = str.substr(-4,2) // 开始截取的下标可以用负数表示
    console.log(str) // 'cd'

    str = str.substr(1,20) // 长度超出最大下标,就相当于省略了参数2
    console.log(str) // cdef
  • substring - 截取字符串

    var str = 'abcdef'
    str = str.substring(1,4) // 参数1是开始截取的下标,参数2是结束下标
    console.log(str) // bcd - 结果不包含结束下标对应的字符

    str = str.substring(1) // 省略参数2,默认截取到末尾
    console.log(str) // bcdef

    str = str.substring(1,1) // 开始下标和结束下标相等就截取到空字符串
    console.log(str) // ''

    str = str.substring(4,1) // 开始下标大于结束下标,就先交换两个参数位置,然后再截取
    console.log(str) // 'bcd'

    str = str.substring(-5,4) // 开始下标或结束下标是负数,就先替换为0,然后开始截取
    console.log(str) // abcd

 

 

 

  • 数学处理

     

    Math常用API

     

    • 圆周率

      Math.PI // 3.1415926535
    • 生成随机数

      Math.random()

      生成的是0~1之间的随机小数,通常在实际项目中需要获取到一个范围内的随机整数,利用这个随机小数封装一个获取范围内的随机整数的函数:

      function getRandom(a,b){
      var max = a;
         var min = b;
         if(a<b){
        max = b;
             min = a;
        }
         return parseInt(Math.random() * (max - min)) + min
      }
    • 向上取整

      向上取整的含义是一个数字的小数部分不够1,将他处理成1。例如:10条数据每页展示3条,前3页都能放3条数据,但是第4页只能放1条数据,虽然占不满1页,但也要占1页

      Math.ceil(3.3) // 4
    • 向下取整

      向下取整跟parseInt()是一个意思,只要整数部分,舍掉小数部分得到整数

      Math.floor(3.9) // 3
    • 四舍五入

      Math.round(3.3) // 3
      Math.round(3.9) // 4
    • 求次方

      Math.pow(2,3) // 2的3次方,参数1是底数,参数2是幂数
    • 绝对值

      Math.abs(-6) // 6
      Math.abs(6) // 6
    • 最大值

      Math.max(9,5,1,3,4,8,2,6) // 9
    • 最小值

      Math.max(9,5,1,3,4,8,2,6) // 1
    • 正弦

      Math.sin(Math.PI*30/180) // 0.5
    • 余弦

      Math.cos(Math.PI*60/180) // 0.5

     

    进制的转换

     

    10进制转其他进制:10进制数字.toString(进制数)

     

    var  x = 110;
    x.toString(2) // 转为2进制
    x.toString(8) // 转为8进制
    x.toString(16) // 转为16进制

     

    其他进制转10进制:parseInt(数据,进制数)

     

    var x = "110" // 这是一个二进制的字符串表示
    parseInt(x, 2) // 把这个字符串当做二进制, 转为十进制

    var x = "70" // 这是一个八进制的字符串表示
    parseInt(x, 8) // 把这个字符串当做八进制, 转为十进制

    var x = "ff" // 这是一个十六进制的字符串表示
    parseInt(x, 16) // 把这个字符串当做十六进制, 转为十进制

     

    时间日期处理

     

    js提供了一个构造函数Date,用来创建时间日期对象。所以跟时间日期有关的操作都是通过时间日期来操作的。

     

    时间日期对象创建

     

    var date = new Date()
    console.log(date) // Tue Jul 30 2019 21:26:56 GMT+0800 (中国标准时间)

     

    创建好的是一个对象,但是当输出的时候被浏览器自动转为字符串输出了。获取到的是当前本地的时间日期对象。如果把本地的时间日期改掉,获取到的时间日期对象会随着本地时间变化。

     

    获取具体的时间日期

     

    通过时间日期对象可以获取到具体的年月日时分秒,甚至毫秒和时间戳。

     

    date.getFullYear(); // 获取到完整的时间日期对象中的年份
    date.getMonth(); // 获取到时间日期对象中的月份 - 这里的月份是通过0~11来描述1~12月的
    date.getDate(); // 获取到时间日期对象中的日
    date.getDay(); // 获取时间日期对象中的星期几
    date.getHours(); // 获取到时间日期对象中的时
    date.getMinutes(); // 获取到时间日期对象中分
    date.getSeconds(); // 获取到时间日期对象中的秒
    date.getMilliseconds(); // 获取到时间日期对象中的毫秒 - 1秒=1000毫秒
    date.getTime(); // 获取到时间日期对象对应的时间戳

     

    时间戳,指的是,格林尼治时间1970年1月1日0点0分0秒到现在走过的毫秒数。利用时间戳可以方便计算时间,例如:计算100天以前是几月几号。

     

    将年月日时分秒放在页面中显示:

     

    var date = new Date();
    var year = date.getFullYear();
    var month = date.getMonth()+1;
    var d = date.getDate();
    var day = date.getDay();
    var hour = date.getHours();
    var minute = date.getMinutes();
    var second = date.getSeconds();
    document.write("现在是北京时间:"+year+"年"+month+"月"+d+"日。星期"+day+"。"+hour+"时"+minute+"分"+second+"秒");

     

    设置时间日期

     

    通过时间日期对象,可以将其中的年月日时分秒进行设置,改变时间日期对象的时间。

     

    date.setFullYear(年份); // 设置时间日期对象中的年份
    date.setMonth(当前月份-1); // 设置时间日期对象中的月份 - 这里的月份是通过0~11来描述1~12月的
    date.setDate(日); // 设置时间日期对象中的日
    date.setHours(时); // 设置时间日期对象中的时
    date.setMinutes(分); // 设置时间日期对象中分
    date.setSeconds(秒); // 设置时间日期对象中的秒
    date.setMilliseconds(毫秒); // 设置时间日期对象中的毫秒
    date.setTime(时间戳); // 设置时间日期对象对应的时间戳 - 直接用时间戳就能将时间日期对象中的年月日时分秒全部改变

     

    星期几是不能设置的,是根据年月日生成的。

     

    创建指定的时间日期对象

     

    我们可以在创建时间日期对象的时候就指定时间:

     

    var date = new Date("年-月-日 时:分:秒") // 也可以是英文版的时间字符串 - Sun May 13,2016
    var date = new Date(年,-1,日,时,分,秒)
    var date = new Date(时间戳)

     

    日期格式化

     

    date.toLocalString();//本地风格的日期格式
    date.toLocaleDateString(); // 获取日期
    date.toLocaleTimeString(); // 获取时间

     

    时间戳的获取

     

    格林威治时间/格林尼治时间

     

    Date.parse("2015-08-24") // 获取1970年到设定时间的毫秒数
    new Date().getTime()
    +new Date();

     

    案例:

     

    两个指定的日期相差多少天

     

    var date1=new Date(2010,10,3);
    var date2=new Date(2017,9,24);
    var day=(date2.getTime()-date1.getTime())/(1000*60*60*24);/*不用考虑闰年否*/
    console.log("相差"+day+"天");

     

    100天以后是哪年哪月哪日

    var date = +new Date()
    date += 100 * 24 * 3600 * 1000
    var newDate = new Date(date)
    var year = newDate.getFullYear()
    var month = newDate.getMonth() + 1;
    var d = newDate.getDate()
    console.log('100天以后是'+year+'年'+month+'月'+d+'日')

  •  

  •  
     


     
     

    js的组成部分

    前面学习的部分是ECMAScript部分,都是基础语法部分。基础语法只是规定的代码如何写,并不能实现很多主流的操作,比如跳转页面,获取浏览器的尺寸等操作。再比如让HTML中的元素动起来。

    所以需要学习BOM来操作浏览器。学习DOM来操作HTML标签。

    BOM

    BOM是三个单词的首拼--Browser Object Model,即浏览器对象模型。

    既然是对象模型,那么所有内容,都是用对象来描述的。

    BOM中最大的对象叫window,是浏览器窗口对象。他包含了很多浏览器的操作。

    window对象中包含的对象
    1572261418821

    浏览器的信息

    浏览器的名称、版本等信息。关于浏览器的信息,window交给了他的子对象navigator去记录。

    console.log(window.navigator.appCodeName); // 返回浏览器的代码名
    console.log(window.navigator.appName); // 返回浏览器的名称
    console.log(window.navigator.appVersion); // 返回浏览器的平台和版本信息
    console.log(window.navigator.cookieEnabled); // 返回指明浏览器是否启用cookie的布尔值
    console.log(window.navigator.platform); // 返回运行浏览器的操作系统平台
    console.log(window.navigator.userAgent); // 返回由客户机发送服务器的user-agent头部的值

    结果:

    浏览器信息
    1564539905455

    使用说明:其实navigator对象是属于window对象的,但是window是所有对象的顶级对象,所以通常在写的时候,可以省略掉window。

    浏览器的历史记录

    历史记录的操作是window的子对象history。可以操作网页的前进和后退。

    history.back(); # 返回到上一个页面,相当于浏览器的后退按钮
    history.forward(); # 前进到下一个页面(下一个页面必须是点击以后的页面),相当于浏览器的前进按钮
    history.go()

    浏览器的地址栏信息

    浏览器的地址栏操作,window对象交给了自己的子对象location对象去处理。

    console.log(location.hash); // 设置或返回从#开始的url --- 锚点
    console.log(location.href); // 设置或返回完整的的url
    console.log(location.search); // 设置或返回url中的参数部分

    方法:

    语法:
    location.assign("要跳转的地址"); # 这个方法是设置要跳转的地址
    location.reload(); # 重新加载本页面
    location.replace() # 使用新地址替换掉旧地址(跳转)

    浏览器的弹出层

    window.alert("恭喜你!");
    window.prompt("请输入数字:",1);
    window.confirm("你确定要删除吗?")

    浏览器窗口尺寸

    • window.innerHeight - 浏览器窗口的高度

    • window.innerWidth - 浏览器窗口的宽度

    var w = window.innerWidth;
    console.log(w);
    var h = window.innerHeight;
    console.log(h);

    说明:

    1. 这两个属性返回的单位是像素

    2. 这两个属性计算的范围包含滚动条的区域

    浏览器的事件

    onload事件:当网页中的所有资源都加在完成之后执行这个事件

    window.onload = function(){
    console.log("当网页中所有资源加载完成才打印");
    }

    使用说明:通常是将script标签放到head标签中的时候使用。因为放在head中默认是获取不到body中的内容的,但是有了这个事件后,就可以了。

    onscroll 滚动事件:当网页滚动条的位置发生改变的时候触发这个事件

    window.onscroll = function () {
     console.log('浏览器滚动了')
    }

    使用说明:浏览器要有滚动条才行。

    浏览器窗口改变事件:resize

    window.onresize = function(){
       // 当浏览器的窗口大小发生改变的时候触发这个事件
    }

    浏览器滚动的距离

    获取文档向下滚动的距离,以下两个都可以:

    • document.documentElement.scrollTop

    • document.body.scrollTop

    window.onscroll = function () {
     var t = document.documentElement.scrollTop;
     console.log(t);
     var t1 = document.body.scrollTop;
     console.log(t1);
    }

    使用说明:这两个的区别在于当前文档有没有doctype,有就用document.documentElement.scrollTop,没有就用document.body.scrollTop

    获取页面向右滚动的距离:

    • document.body.scrollLeft

    • document.documentElement.scrollLeft

    使用方式同上。

    使用兼容写法:

    var t = document.documentElement.scrollTop || document.body.scrollTop;
    var l = document.documentElement.scrollLeft || document.body.scrollLeft;

    短路运算

    当我们将一个变量赋值给另一个变量的时候,通常需要做判断:如果这个变量有值就赋值,如果变量没有值或是undefined或null的时候,就赋一个默认的值。这个判断可以省略分支结构使用一个简短的语法来表示 - 短路运算。

    短路运算的符号有两个:||&&

    var a;
    var b = a || 2; // 如果a有值,就将值赋给b,如果a没有值,就给b赋2 - 此时是将2赋给b

    var a = 3;
    var b = a || 2; // 如果a有值,就将值赋给b,如果a没有值,就给b赋2 - 此时是将a的值赋给b

    其中的原理:赋值时,先将运算符左右两边的值转为布尔值来进行判断,因为是使用或者符号来连接的,所以如果左边为true,那已经能确定整体的结果是true,此时就不会执行后面的值,就将这个值赋给变量了;如果左边为false,并不能确定整体的结果,所以需要执行到后面,就会将后面的值赋给变量。

    var a;
    var b = a && 2; // 如果a有值,就将2赋值给b,如果a没有值,就将a赋给变量 - 此时是将a赋给b

    var a = 3;
    var b = a && 2; // 如果a有值,就将2赋值给b,如果a没有值,就将a赋给变量 - 此时是将2赋给b

    其中的原理:赋值赋值时,先将运算符左右两边的值转为布尔值来进行判断,因为是使用并且符号来连接的,所以如果左边为true,那还不能确定整体的结果是,此时就会执行后面的值,就将这个值赋给变量了;如果左边为false,已经能确定整体的结果,所以不需要执行到后面,就会将前面的值赋给变量。

    因为在赋值前的判断,是将左右两边的值转为布尔值来判断的,所以只要能转为布尔值的数据都可以进行,包含:

    0
    null
    undefined
    false
    ''

    定时器

    延迟执行:

    var timerId = setTimeout(function () {
     console.log('我执行了')
    }, 1000)
    console.log(timerId) // 1

    使用说明:第一个参数是要执行的函数,第二个参数延迟的时间(单位毫秒)。返回一个数字,表示当前页面中第几个定时器。

    每间隔一段时间执行:

    var timerId = setInterval(function () {
     console.log('我执行了')
    }, 1000)

    使用说明:第一个参数是要执行的函数,第二个参数是间隔的时间(单位毫秒)。返回一个数字,表示当前页面中第几个定时器。

    关闭定时器:

    定时器返回的数字,就是用来关闭定时器的

    clearTimeout(timerId); // 关闭延迟执行的定时器
    clearInterval(timerId); // 关闭间隔执行的定时器

    使用说明:其实这两个方法可以混用。

    var timerId = setTimeout(function () {
     console.log('倒计时定时器')
    }, 1000)
    // 关闭延迟执行定时器
    clearInterval(timerId)

    var timerId2 = setInterval(function () {
     console.log('间隔定时器')
    }, 1000)
    // 关闭间隔定时器
    clearTimeout(timerId2)

    异步操作

    异步和同步的概念

    张三叫李四一起去吃饭,张三说他还有作业没做完,让李四先去,李四去吃饭,张三在写作业,这两个人做的事情不一样,但是在同一时间段内,两个人的事情在同时做,这就是异步。

    张三叫李四一起去吃饭,张三说他还有作业没做完,让李四等一下,李四就等张三做完作业后两个人才一起去吃饭。这就是同步。

    同步的操作需要等待,执行起来是有顺序可循的;异步的操作不需要等待,两件事情是同行进行的。

    我们平常写的代码都是同步代码,定时器我们接触到的第一个异步代码。

    js的特点是单线程的,也就是同一时间只能做一件事情,所以js会将异步代码交给浏览器去处理,因为浏览器是多线程的。

    js的线程,会先将所有同步代码执行完,与此同时,浏览器也在处理异步代码(例如正在等待时间),当浏览器中的异步代码到了应该执行的时候了,会将需要执行的异步代码放在一个队列中,进行排队等候;当js线程将所有同步代码执行结束后,会从队列中拿出第一个需要执行的代码去执行,执行过一个以后,再次到队列中拿出第二个需要执行的代码去执行。。。。

    js的异步操作,是在所有同步代码执行完成以后才执行异步代码

    一般情况代码是按顺序执行的,上一行代码执行结束之前,下一行代码一直在等待,这是同步机制

    同步执行示意图
    1565952873628

    异步代码是等待同步代码都执行完成以后,才运行异步代码,如下图:

    异步执行示意图
    1565952829709

    DOM

    DOM的全拼是:Document Object Model,叫做文档对象模型,主要用于操作html文档。例如,改变标签的北京颜色,让标签移动产生动画。。。。

    DOM中的顶级对象是document,言外之意,DOM其实是属于BOM的。

    例如:

    window.document.write();
    window.document.bgColor="red";

    html基本结构的操作:

    1. document.body :body比较常用, 并且在页面中是唯一的, 因此可以使用document.body直接获取

    2. document.documentElement : 可以获取html元素及其所有内容

    3. document.head : 可以直接获取head元素

    4. document.title : 可以直接获取title的文本

    获取元素

    在js中,标签的id名,可以当做是变量,直接就能代表这个标签元素,但是,id名可以随便定义,但是变量名不能随便定义,所以使用id名代表标签是有风险的。所以需要通过方法来获取到标签元素,自己定义给变量,可以避免这种风险。

    通过document获取节点

    document.getElementById("标签id名"); // 通过标签的id名获取标签
    document.getElementsByTagName("标签名"); // 通过标签名获取标签
    document.getElementsByClassName("标签类名"); // 通类名获取标签
    document.getElementsByName("标签的name属性的值"); // 通过标签的name属性获取标签
    // 上述4种获取标签的方法,除了通过id可以准确获取到元素,别的方法都是只能获取到元素的集合(类数组)

    使用css选择器获取元素:

    documen.querySelector(css选择器); // 获取到匹配css的第一个元素
    documen.querySelectorAll(css选择器); // 获取到匹配css的所有元素

    属性操作

    自定义属性

    元素.setAttribute(属性名,属性值) # 设置元素的属性
    元素.getAttribute(属性名); # 获取元素属性
    元素.removeAttribute(属性名); # 删除元素属性

    元素自带属性

    元素.属性名 = 值;
    console.log(元素.属性名);

    例:

    btn.onclick=function(){
       img.src = '2.jpg';
    }

     

    内容操作

    语法:
    元素.innerHTML # 代表元素中的所有内容(包含标签)
    元素.innerText # 代表元素中的文本内容
    表单元素.value
    # 单标签操作内容其实就是在操作元素的属性

    例:

    <body>
    <div id="box" introduce="区域"><p>我是盒子</p></div>
    </body>
    <script type="text/javascript">
    document.getElementById("box").innerText = "今天你要嫁给我";
    var text = document.getElementById("box").innerText;
    document.write(text);
    document.getElementById("box").innerHTML = "<a href='http://www.baidu.com'>百度</a>";
    var content = document.getElementById("box").innerHTML;
    console.log(content);

    样式设置

    元素.style.css属性名 = css属性值; # 给标签设置样式

    例:

    <body>
    <style type="text/css">
    #box{
    width:100px;
    height:100px;
    background:#f00;
    }
    </style>
    <input type="button" id="btn" value="走你">
    <div id="box"></div>
    </body>
    <script type="text/javascript">
    var n = 0;
    document.getElementById("btn").onclick=function(){
    n += 100;
    document.getElementById("box").style.marginLeft = n + "px";
    }
    </script>

    这样设置的样式都是行内样式。

    元素类名

    使用元素的className属性可以设置元素的类名,也可以获取类名

    <body>
     <div class="box"></div>

     <script>
       var div = document.querySelector('div')
      div.className = 'test'
       console.log(div) // <div class="test"></div>
         
       console.log(div.className) // test
     </script>
    </body>




 

 

 兼容性最好

 

 

 

 

 

 

 

 

 错误

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

总结

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 本次小结:
    重点es5新增的数组方法:
    'indexOf方法'
    var a = arr.indexOf(60)查找元素是否存在在数组中,如果存在,返回该元素在数组中的下标,如果不存在,返回-1

    'forEach方法'
     var a = arr.forEach(function(v,i,a){
         v,i,a都是可选项
         v代表每个遍历出来的值
         i代表每个遍历出来的值的下标
         a代表正在遍历的数组
     }

     'map方法'
     var a = Int8Array.map(function(v){将每个元素都经过函数处理,处理成新的元素,将新的元素组成数组返回
        一样也有v,i,a都是可选项
        var s = v*1.3
        return s
     })

     'filter方法'
     var a = arr.filter(function(v){它会自动遍历数组,把每一位值跟条件比较,不成立的就过滤,成立的就组成新的数组并返回
         return v<60
         })

DOM

DOM 就是我们 html 结构中一个一个的节点构成的。不光我们的标签是一个节点,我们写的文本内容也是一个节点,注释,包括空格都是节点。

DOM节点分三种:元素节点、文本节点、属性节点。元素节点就是我们获取到的标签元素;标签里面的文本就是文本节点、标签上的属性就是属性节点。

元素节点

就是我们各种获取方法获取到的标签元素

document.getElementById();
document.querySeletor();
document.querySeletorAll();

属性节点

我们通过获取属性的方法获取到的标签属性

标签元素.getAttribute();

文本节点

我们通过innerText获取到的文本内容就是文本节点

获取节点

  • 获取所有子节点childNodes

    <body>
       <div id="box">
           <p>
               <span>span标签</span>
           </p>
       </div>
    </body>
    <script type="text/javascript">
    var Odiv = document.getElementById("box");
    console.log(Odiv.childNodes);
    </script>

    说明:获取到的时所有节点,包含文本节点、元素节点。元素节点只有子元素,不包括子元素里面的内容

    获取元素所有子节点
    1564913596865

    看图得知:第一个节点时文本节点,代表标签中间的换行和空格,第二个节点是元素节点,第三个节点是文本节点,又是标签中间的换行和空格

  • 获取所有子元素节点children

    <body>
       <div id="box">
           <p class="part">
               <span>span标签</span>
           </p>
       </div>
    </body>
    <script type="text/javascript">
    var Odiv = document.getElementById("box");
    </script>

    说明:只获取元素节点,不包含文本节点

    获取所有子元素节点
    1564913668953

    看图得知:获取到的是一个伪数组,是一个集合。

  • 获取第一个子节点firstChild

    <body>
       <div id="box">
           <p class="part">
               <span>span标签</span>
           </p>
           <a href="#">链接</a>
       </div>
    </body>
    <script type="text/javascript">
    var Odiv = document.getElementById("box");
    console.log(Odiv.firstChild);
    </script>

    说明:只获取第一个节点,其实就相当于childNodes中的第一个。

    获取第一个子节点
    1564914062968

    看图得知:第一个节点是文本节点,相当于Odiv.childNodes[0]。因为div和p标签中间有换行和空格

  • 获取最后一个子节点

    <body>
       <div id="box">
           <p class="part">
               <span>span标签</span>
           </p>
           <a href="#">链接</a>
       </div>
    </body>
    <script type="text/javascript">
    var Odiv = document.getElementById("box");
    console.log(Odiv.lastChild);
    </script>

    说明:只获取最后个节点,其实就相当于childNodes中的最后一个。

    获取最后一个子节点
    1564914062968

    看图得知:第一个节点是文本节点,相当于Odiv.childNodes[childNodes.length-1]

  • 获取第一个子元素节点firstElementChild

    <body>
       <div id="box">
           <p class="part">
               <span>span标签</span>
           </p>
           <a href="#">链接</a>
       </div>
    </body>
    <script type="text/javascript">
    var Odiv = document.getElementById("box");
    console.log(Odiv.firstElementChild);

    说明:只获取元素节点,不会是文本节点。

    获取第一个元素节点
    1564914338315

    看图得知:获取到的时第一个子元素节点。

  • 获取最后一个子元素节点lastElementChild

    <body>
       <div id="box">
           <p class="part">
               <span>span标签</span>
           </p>
           <a href="#">链接</a>
       </div>
    </body>
    <script type="text/javascript">
    var Odiv = document.getElementById("box");
    console.log(Odiv.lastElementChild);

    说明:只获取元素节点,不会是文本节点。

    获取第一个元素节点
    1564914496519

    看图得知:获取到的时最后一个子元素节点。

  • 获取下一个兄弟节点nextSibling

    <body>
       <div id="box">
           <p class="part">段落标签</p>
           <a href="#">链接</a>
           <span>span标签</span>
       </div>
    </body>
    <script type="text/javascript">
    var oA = document.querySelector("a");
    console.log(oA.nextSibling);
    </script>

    说明:获取的是节点,有可能时文本节点。

    获取下一个兄弟节点
    1564916436427

    看图得知:获取的是当前节点的下一个节点,不是元素。

  • 获取上一个兄弟节点previousSibling,同上。

  • 获取当前节点的下一个兄弟元素节点nextElementSibling

    <body>
       <div id="box">
           <p class="part">段落标签</p>
           <a href="#">链接</a>
           <span>span标签</span>
       </div>
    </body>
    <script type="text/javascript">
    var oA = document.querySelector("a");
    console.log(oA.nextElementSibling);
    </script>

    说明:获取是元素节点。

    获取下一个兄弟元素节点
    1564916663987

    看图得知:获取到的是下一个兄弟,是元素节点

  • 获取当前节点的下一个兄弟元素节点previousElementSibling,同上。

  • 获取父节点parentNode,和parentElement一样

    <body>
       <div id="box">
           <p class="part">段落标签</p>
           <a href="#">链接</a>
           <span>span标签</span>
       </div>
    </body>
    <script type="text/javascript">
    var oA = document.querySelector("a");
    console.log(oA.parentNode);
    </script>

    说明:获取到的是元素节点。

    获取父节点
    1564916800628

    父节点是元素节点。

  • 获取元素的属性节点attributes

    <body>
       <a href="#" title="跳转百度">链接</a>
    </body>
    <script type="text/javascript">
    var oA = document.querySelector("a");
    console.log(oA.attributes);
    </script>

    说明:获取到是所有属性的集合。

    获取属性节点
    1564917054076

    结果是所有属性组成的伪数组。

 

节点是有不同分类的。获取到节点后,可以通过节点的属性来判断节点的类型。

常用的操作:

获取所有子元素

获取上一个兄弟元素

获取下一个兄弟元素

获取父元素

节点属性

  • nodeType:  节点类型:元素节点 = 1 属性-2(过时) 注释-8 文本-3 参考链接

    <body>
       <div id="box" name="hezi">
           <p class="part" >段落标签</p>
           <a href="#" title="跳转百度">链接</a>
           <span>span标签</span>
           <!-- div结束 -->
       </div>
    </body>
    <script type="text/javascript">
    var Odiv = document.getElementById("box"); // div元素节点
    var text = Odiv.firstChild; // 文本节点(中间的换行和空格)
    var note = Odiv.lastChild.previousSibling; // 换行和空格前面是注释
    var attr = Odiv.attributes[0]; // div的第一个属性,是属性节点
    console.log(Odiv.nodeType); // 1
    console.log(text.nodeType); // 3
    console.log(note.nodeType); // 8
    console.log(attr.nodeType); // 2
    </script>

    说明:nodeType属性的值不一样,代表节点的类型不同。

  • nodeName: 节点名称

    <body>
       <div id="box" name="hezi">
           <p class="part" >段落标签</p>
           <a href="#" title="跳转百度">链接</a>
           <span>span标签</span>
           <!-- div结束 -->
       </div>
    </body>
    <script type="text/javascript">
    var Odiv = document.getElementById("box"); // div元素节点
    var text = Odiv.firstChild; // 文本节点(中间的换行和空格)
    var note = Odiv.lastChild.previousSibling; // 换行和空格前面是注释
    var attr = Odiv.attributes[0]; // div的第一个属性,是属性节点
    console.log(Odiv.nodeName); // DIV
    console.log(text.nodeName); // #text
    console.log(note.nodeName); // #comment
    console.log(attr.nodeName); // id
    </script>

    说明:元素节点的节点名称是大写的标签名;文本节点的节点名称是#text;注释节点的节点名称是#comment;属性节点的节点名称是属性名。

  • nodeValue: 节点值

    <body>
       <div id="box" name="hezi">
           <p class="part" >段落标签</p>
           <a href="#" title="跳转百度">链接</a>
           <span>span标签</span>
           <!-- div结束 -->
       </div>
    </body>
    <script type="text/javascript">
    var Odiv = document.getElementById("box"); // div元素节点
    var text = Odiv.firstChild; // 文本节点(中间的换行和空格)
    var note = Odiv.lastChild.previousSibling; // 换行和空格前面是注释
    var attr = Odiv.attributes[0]; // div的第一个属性,是属性节点
    console.log(Odiv.nodeValue); // null
    console.log(text.nodeValue); // "换行和空格"
    console.log(note.nodeValue); // "div结束" -- 注释内容
    console.log(attr.nodeValue); // "box" -- 属性值
    </script>

    说明:元素节点没有节点值;文本节点的值就是文本内容;注释节点的内容就是注释的内容;属性节点的内容就是属性的值。

案例:childNodes/过滤空白节点

function delSpaceDom(parentNode) {
     var sub_child = parentNode.childNodes;
     for (var i = 0; i < sub_child.length; i++) {
         if(sub_child[i].nodeType == '3' && sub_child[i].nodeName == '#text' && !/\S/.test(sub_child[i].nodeValue)){//文本节点并且是空的文本节点时,将空文本节点删除
             parentNode.removeChild(sub_child[i]);
        }
    }
     return parentNode.childNodes;
}

 

节点操作

创建节点

属性名语法功能
createElement document.createElement(元素标签) 创建元素节点(创建标签)
createAttribute document.createAttribute(元素属性) 创建属性节点(创建属性,只有属性名,没有属性值)
createTextNode document.createTextNode(文本内容) 创建文本节点(创建了一个内容)

例:

var div = document.createElement("div"); // 创建元素节点
var attr = document.createAttribute("name"); // 创建属性节点
attr.value = 'mybox'; // 给属性节点赋值
div.setAttributeNode(attr); // 将属性节点放入元素节点中
var text = document.createTextNode("内容"); // 创建文本节点
div.appendChild(text); // 将文本节点放入元素中
console.log(div); // 输出元素节点

访问效果:

创建节点及使用
1565971970464

 

插入节点

属性名语法功能
appendChild 父节点.appendChild(所添加的新节点) 向节点的子节点列表末尾添加新的子节点
insertBefore 父节点.insertBefore(所要添加的新节点,已知子节点) 在已知的子节点前插入一个新的子节点

例:

<body>
<div id="myid">
大盒子
<div>小何字</div>
</div>
<script type="text/javascript">
var p = document.createElement("p");
var a = document.getElementsByTagName("div")[1];
myid.insertBefore(p,a);
// document.getElementById("myid").appendChild(p);
</script>
</body>

替换节点

将某个子节点替换为另一个

语法:
父节点.replaceChild(要插入的新节点,将被替换的老元素);

例:

<body>
<div id="myid">
大盒子
<div>小何字</div>
</div>
<script type="text/javascript">
var p = document.createElement("p");
var a = document.getElementsByTagName("div")[1];
myid.replaceChild(p,a);
</script>
</body>

复制节点

根据原来的节点复制一个节点出来

语法:
需要被复制的节点.cloneNode(param);

使用说明:param的值是布尔值,为true时表示复制当前节点及其所有子节点(深复制),为false时,表示仅复制当前节点,缺省值为false(浅复制)

<body>
<div id="myid">
大盒子
</div>
<script type="text/javascript">
var n = myid.cloneNode(true);
console.log(n);
</script>
</body>

删除节点

删除指定元素的某个子节点

语法:
父元素.removeChild(要删除的节点);

例:

<body>
<div id="myid">
大盒子
<p id="part">段落</p>
</div>
<script type="text/javascript">
myid.removeChild(part);
</script>
</body>

节点操作总结

创建元素节点

追加子节点

添加到指定子节点前面

复制节点 -- 浅复制和深复制

删除节点

获取元素样式

我们通过元素节点的style属性赋值,就可以给元素添加样式,那能不能通过stlye属性获取元素样式呢?

<body>
<style>
   div{background: #0f0;}
</style>
<div style="width:100px;height:100px;border:1px solid #000;"></div>
</body>
<script type="text/javascript">
var ODiv = document.getElementsByTagName("div")[0]; // 获取到div元素
console.log(ODiv.style.width);
console.log(ODiv.style.background);
</script>

访问结果:

使用style属性获取元素样式
1564918994198

看图得知:给元素设置的行内样式获取到了,但是获取不到内联样式。

也就是说,style属性只能获取到元素的行内样式。

那么如何获取元素的内联样式以及外联样式呢?

通过window对象的getComputedStyle方法:

语法:

window.getConputedStyle(元素).css属性;

返回一个对象,这个对象中包含了元素所有的样式。

例:

<body>
<style>
   div{background: #0f0;}
</style>
<div style="width:100px;height:100px;border:1px solid #000;"></div>
</body>
<script type="text/javascript">
var ODiv = document.getElementsByTagName("div")[0]; // 获取到div元素
var bg = window.getcomputedStyle(ODiv).background;
console.log(bg);
</script>

访问结果:

获取元素样式
1564919362679

这个方法在IE中不起作用,那在IE中用什么获取样式?

使用元素的currentStyle属性:

语法:

元素.currentStyle;

这个对象返回的也是一个包含元素所有样式的对象

例:

<body>
<style>
   div{background: #0f0;}
</style>
<div style="width:100px;height:100px;border:1px solid #000;"></div>
</body>
<script type="text/javascript">
var ODiv = document.getElementsByTagName("div")[0]; // 获取到div元素
var ODivStyles = ODiv.currentStyle;
console.log(ODivStyles);
</script>

访问结果:

IE下获取元素样式
1564919644470

节点操作案例:qq菜单案例

<link rel="stylesheet" href="./font/iconfont.css">
<style>
*{
   padding: 0;
   margin: 0;
   list-style:none;
}
ol{
   width:300px;
   background-color: pink;
   padding-left:10px;
   margin:50px auto;
}
h2{
   font-size:20px;
   height:30px;
   line-height:30px;
}
ol ul{
   display:none;
}
ol ul li{
   font-size:18px;
   height:24px;
   line-height:24px;
   padding-left:2em;
   background-color: #666;
   color:#fff;
   margin:5px 0;
}
</style>
</head>
<body>
<ol>
   <li>
       <h2><i class="iconfont icon-arrowRight"></i>我的好友</h2>
       <ul>
           <li>张三</li>
           <li>李四</li>
           <li>王五</li>
       </ul>
   </li>
   <li>
       <h2><i class="iconfont icon-arrowRight"></i>我的坏友</h2>
       <ul>
           <li>张小三</li>
           <li>李小四</li>
           <li>王小五</li>
       </ul>
   </li>
   <li>
       <h2><i class="iconfont icon-arrowRight"></i>黑名单</h2>
       <ul>
           <li>张大三</li>
           <li>李大四</li>
           <li>王大五</li>
       </ul>
   </li>
</ol>
</body>
<script src="./js/jquery.js"></script>
<script type="text/javascript">
var h2 = document.querySelectorAll("h2");
var onOff = true;
for(var i=0;i<h2.length;i++){
   h2[i].onclick=function(){
       var oi = this.querySelector("i");
       var ul = this.nextElementSibling;
       var attr = ul.getAttribute("name");
       // var s = window.getComputedStyle(ul).display;
       // if(s == "none"){
       if(!attr){
           for(var j=0;j<h2.length;j++){
               var oii = h2[j].querySelector("i");
               var ull = h2[j].nextElementSibling;
               oii.className = 'iconfont icon-arrowRight';
               ull.style.display = 'none';
          }
           oi.className = 'iconfont icon-changyongtubiao-xianxingdaochu-zhuanqu-';
           ul.style.display = 'block';
           ul.setAttribute("name","block");
      }else{
           oi.className = 'iconfont icon-arrowRight';
           ul.style.display = 'none';
           ul.removeAttribute("name");
      }
       /*
      用样式判断的时候不要使用颜色的值 - 颜色值在内部有可能会变成rgb,判断不准确
      判断的时候不要使用路径去判断
      */
  }
}
</script>

效果图:

qq菜单案效果

获取元素的坐标和大小

在DOM中有一些offset开头的属性,在实际开发中用的比较多。他们可以获取元素的大小、元素的位置等。

获取元素的宽度和高度

语法:

元素.offsetWidth; # 获取元素的宽度
元素.offsetHeight; # 获取元素的高度

例:

<style>
   .box{
       width:100px;
       height:50px;
       background:red;
  }
</style>
<div class="box">
   
</div>
<script>
var box = document.querySeletor(".box");
console.log(box.offsetWidth,box.offsetHeight); // 120 70
</script>

使用说明:

  1. 这两个属性获取到的元素大小是包含边框的。

  2. 这两个属性获取到的结果是数字,方便计算。

  3. 这个属性只能获取不能设置,是只读属性。

这两个属性其实和通过样式获取到的值是一样的,样式中的宽高是包含单位的,不方便计算,所以在需要使用宽高来计算的时候使用这两个属性更加方便。

获取定位原点参考的父元素

我们知道,当给一个元素设置定位的时候,参考的原点位置需要一个设置定位的父元素,如果父元素没有设置过定位,那就找父元素的父元素,一直往上,直到找到HTML,那就以html作为定位的参考元素。

offset开头的属性中有一个属性就是找这个参考元素的。

语法:

元素.offsetParent; # 获取定位需要参考的元素

例:

<style>
   .box{
       width:300px;
       height:200px;
       background:red;
position:relative;
  }
.smallBox{
width:100px;
height:100px;
background:blue;
position:absolute;
left:100px;
top:50px;
}
</style>
<div class="box">
   <div class="smallBox"></div>
</div>
<script>
var smallBox = document.querySelector(".smallBox");
console.log(smallBox.offsetParent);
</script>

效果:

设置定位的参考元素
1572414188243

当父元素没有设置定位的时候,定位参考的元素应该是html,但在这里输出的是body。

例:

<style>
   .box{
       width:300px;
       height:200px;
       background:red;
  }
.smallBox{
width:100px;
height:100px;
background:blue;
position:absolute;
left:100px;
top:50px;
}
</style>
<div class="box">
   <div class="smallBox"></div>
</div>
<script>
var smallBox = document.querySelector(".smallBox");
console.log(smallBox.offsetParent);
</script>

效果:

父元素没有设置定位的时候,参考元素是body
1572414322107

获取元素的位置

offset开头的属性中还有有可以获取元素的位置的。

语法:

元素.offsetLeft; # 获取元素左边的距离
元素.offsetTop; # 获取元素上边的距离

例:

<style>
   .box{
       width:300px;
       height:200px;
margin:atuo;
       background:red;
position:relative;
  }
.smallBox{
width:100px;
height:100px;
background:blue;
position:absolute;
left:100px;
top:50px;
       transform:translateX(10px);
margin-left:20px;
}
</style>
<div class="box">
   <div class="smallBox"></div>
</div>
<script>
var smallBox = document.querySelector(".smallBox");
console.log(smallBox.offsetLeft,smallBox.offsetTop);
</script>

效果:

元素左边的距离
1572414655094

使用说明:

  1. 获取到的值包括外间距,包括设置过的定位的值。

  2. 这个定位过的值其实是自身到offsetParent的距离。

如果父元素没有设置过定位,那得到的值是自身到body的距离。如果自己也没有设置过定位,那就是自己到html的距离。

例:

<style>
   .box{
       width:300px;
       height:200px;
       background:red;
  }
.smallBox{
width:100px;
height:100px;
background:blue;
}
</style>
<div class="box">
   <div class="smallBox"></div>
</div>
<script>
var smallBox = document.querySelector(".smallBox");
console.log(smallBox.offsetLeft,smallBox.offsetTop);
</script>

效果:“

自身到html的距离
1572414914221

也就是说,获取位置的时候,首先是要找到设置过定位的父元素,如果找到了,就是从父元素开始计算。如果没找到,就从body开始计算,如下图所示

offset系列总结示意图
1564540913378

client获取元素大小

使用元素的clientWidth和属性clientHeight属性也能获取到元素的大小

语法:

元素.clientWidth; # 获取元素的宽度
元素.clientHeight; # 获取元素的高度

例:

<style>
   .box{
       width:100px;
       height:50px;
       background:red;
  }
</style>
<div class="box">
   
</div>
<script>
var box = document.querySeletor(".box");
console.log(box.clientWidth,box.clientHeight); // 100 50
</script>

使用说明:使用这两个属性获取到的元素的大小是不包含边框的大小。

和offset获取宽高的比较:

<style>
   .box{
       width:100px;
       height:50px;
       background:red;
       border:10px solid #000;
  }
</style>
<div class="box">
   
</div>
<script>
var box = document.querySelector(".box");
// 不包含边框的宽和高
console.log(box.clientWidth,box.clientHeight); // 100 50
// 包含边框的宽和高
console.log(box.offsetWidth,box.offsetHeight); // 120 70
</script>

结果:

获取宽高的比较
1572407677428

 

DOM获取窗口大小

BOM有获取浏览器窗口大小的方法:

window.innerWidth
window.innerHeight

这两个获取窗口大小的时候,包含了滚动条的范围。

DOM也有获取窗口大小的方法

document.documentElement.ClientWidth
document.documentElement.clientHeight

DOM获取的大小中不包含滚动条的范围。

DOM获取body的尺寸

document.body.clientWidth
document.body.ClientHeight

事件对象(上)

事件复习

事件三要素: 事件源 + 事件名称 + 事件处理程序

  • 事件源 : 谁触发这个事件 (按钮 btn)

  • 事件名称 : 触发了什么事件 (点击click事件)

  • 事件处理程序 : 事件触发后要执行的代码(函数形式)----可以是有名字的函数,要不要加小括号?不加

事件类型

在事件对象中有个一个属性type可以获取到当前事件的类型。

window.onload = function(e){
   var ev = e || window.event;
   console.log(ev.type); // load
}

 

鼠标事件

事件描述
click 左键单击
contextmenu 右键单击
dblclick 双击
mousedown 左键按下
mouseup 左键弹起
mouseover 鼠标放上去(在子元素上也会触发)
mouseout 鼠标离开
mouseenter 鼠标放上去
mouseleave 鼠标离开
mousemove 鼠标移动事件
mousewheel 鼠标滚轮事件

注意:鼠标滚轮事件有兼容性问题,在IE、Chrom中是mousewheel,在FireFox中是DOMMouseScroll,且在FirFox中不能使用on来绑定。在IE和Chrom中向上滚动,事件对象中的wheelDelta是120,向下滚动是-120,在FirFox中向上滚动,事件对象中的e.detail是3,向下滚动是-3。

案例:星星评分

<body>
<img src="./images/rank_3.gif" alt=""><img src="./images/rank_4.gif" alt="">
<img src="./images/rank_3.gif" alt=""><img src="./images/rank_4.gif" alt="">
<img src="./images/rank_3.gif" alt=""><img src="./images/rank_4.gif" alt="">
<img src="./images/rank_3.gif" alt=""><img src="./images/rank_4.gif" alt="">
<img src="./images/rank_3.gif" alt=""><img src="./images/rank_4.gif" alt="">
</body>
<script type="text/javascript">
var imgs = document.querySelectorAll("img");
for(var i=0;i<imgs.length;i++){
   imgs[i].index = i;
   imgs[i].onmouseover=function(){
       for(var j=0;j<=this.index;j++){
           if(j%2==0){
               imgs[j].src = './images/rank_1.gif'
          }else{
               imgs[j].src = './images/rank_2.gif'
          }
      }
       for(var j=this.index+1;j<imgs.length;j++){
           if(j%2==0){
               imgs[j].src = './images/rank_3.gif'
          }else{
               imgs[j].src = './images/rank_4.gif'
          }
      }
  }
}
</script>

效果图:

星星评分效果图

浏览器事件

事件描述
load 加载
scroll 滚动
resize 大小改变

键盘事件

事件描述
keydown 按下
keyup 弹起
keypress 敲打

键盘事件除了用window可以触发之外,还可以使用document,或者表单元素。总之是可以选中的元素。例如div就不行。

表单事件

事件描述
submit 提交表单
focus 获取焦点
blur 失去焦点
change 内容改变并失去焦点
input input的value值改变

使用说明:input事件在低版本的IE中不兼容,使用onpropertychange代替。

事件流

每个事件发生的时候,都会有一个触发并执行的过程,也就是事件的传播过程,我们称之为事件流。

简单来说,事件流就是事件从发生到执行结束的流程。

事件流包含3个阶段:捕获阶段、目标阶段、冒泡阶段

事件捕获阶段:事件开始由顶层元素触发,然后逐级向下传播,直到目标元素,依次执行其身上绑定的事件。

事件目标阶段(处理阶段):触发当前自身的事件。

事件冒泡阶段:事件由目标元素先接收,然后逐级向上传播,达到最顶层元素,依次执行其身上绑定的事件。

事件流

事件执行的流程是先捕获阶段——》再目标元素阶段——》最后冒泡阶段。

目标元素的事件是在目标阶段执行,其他事件会在冒泡阶段执行。每个事件只会执行一次,也就是说如果在冒泡阶段执行了事件,就不会在捕获阶段执行。

例:

<body>
<style>
   #big{
       width: 200px;
       height: 200px;
       border:1px solid #000;
  }
   #middle{
       width: 150px;
       height: 150px;
       background: #abcdef;
  }
   #small{
       width: 100px;
       height: 100px;
       background: red;
  }
</style>
<div id="big">
  大盒子的内容
   <div id="middle">
      中盒子的内容
       <div id="small">
          小盒子的内容
       </div>
   </div>
</div>
</body>
<script type="text/javascript">
big.onclick=function(){
   console.log(this.innerText);
   console.log("大盒子的内容完毕");
}
middle.onclick=function(){
   console.log(this.innerText);
   console.log("中盒子的内容完毕");
}
small.onclick=function(){
   console.log(this.innerText);
   console.log("小盒子的内容完毕");
}
</script>

访问效果:

冒泡示例图
1565864960484

点击小盒子,发现小盒子事件完毕后,中盒子的事件也被触发了,接着大盒子的事件也被触发了。这就是说目标元素的事件在目标阶段执行,其他事件会在冒泡阶段执行。

思考:如何让事件在捕获阶段执行?

需要使用另外一种事件绑定方式。

事件的绑定方式

事件可以绑定在行内:

<button onclick="alert(123)">按钮1</button>
<button onclick="fn()">按钮2</button>
<script>
   function fn(){
       alert(456)
  }
</script>

使用on加事件类型绑定事件:

使用on来绑定事件有弊端:同一个事件只能给一个元素绑定一次。

<body>
<button id="btn">按钮</button>
</body>
<script>
btn.onclick=function(){
   console.log("第一次单击");
}
btn.onclick=function(){
   console.log("第二次单击");
}
</script>

访问效果:

事件覆盖
1565863839505

解决方案:

使用addEventListener()

语法:

obj.addEventListener(type,handle,false);
# 参数1:给元素绑定的事件类型,如:click,mouseover。。。
# 参数2:处理事件的函数
# 参数3:是否在冒泡阶段执行,true在捕获阶段执行,false在冒泡阶段执行

例:

<body>
<button id="btn">按钮</button>
</body>
<script>
document.getElementById("btn").addEventListener("click",handle,false);
function handle(){
   console.log("第一次点击");
}
document.getElementById("btn").addEventListener("click",handle1,false);
function handle1(){
   console.log("第二次点击");
}
</script>

效果:

同一类型事件给元素绑定多次
1565864342421

使用说明:这个方法在IE低版本浏览器中不兼容。在IE低版本浏览器中使用attachEvent()来代替。

语法:

obj.attachEvent('on' + type,handle);
# type表示事件类型
# handle表示处理事件的函数

使用说明:这种写法,有个特点:顺序注册事件,执行的时候是倒叙执行。

例:

<body>
<button id="btn">按钮</button>
</body>
<script>
document.getElementById("btn").attachEvent("onclick",handle,false);
function handle(){
   console.log("第一次点击");
}
document.getElementById("btn").attachEvent("onclick",handle1,false);
function handle1(){
   console.log("第二次点击");
}
</script>

运行结果:

IE中绑定事件执行
1574645776142

让事件在捕获阶段执行:

<body>
<style>
   #big{
       width: 200px;
       height: 200px;
       border:1px solid #000;
  }
   #middle{
       width: 150px;
       height: 150px;
       background: #abcdef;
  }
   #small{
       width: 100px;
       height: 100px;
       background: red;
  }
</style>
<div id="big">
  大盒子的内容
   <div id="middle">
      中盒子的内容
       <div id="small">
          小盒子的内容
       </div>
   </div>
</div>
</body>
<script>
document.getElementById("small").addEventListener("click",Click,true);
document.getElementById("middle").addEventListener("click",Click,true);
document.getElementById("big").addEventListener("click",Click,true);
function Click(){
   console.log(this.innerText);
}
</script>

执行效果:

捕获阶段执行事件
1565866642122

点击小盒子的时候,先触发大盒子的事件,再触发中盒子的事件,最后触发小盒子的事件。

在IE低版本浏览器中的事件没有捕获阶段,只有冒泡阶段。

通用的绑定和解绑事件

将三种方式的绑定和解绑综合起来的兼容写法:

绑定函数

function bind(ele,type,callback){
if(ele.addEventListener){
ele.addEventListener(type,callback,false);
}else if(ele.detachEvent){
ele.attachEvent("on"+type,callback);
  }else{
       ele["on" + type] = callback;
  }
}

参数说明:

  • ele:将要绑定事件的对象

  • type:事件类型

  • callback:处理事件的函数

解绑函数

function unbind(ele,type,callback){
if(ele.addEventListener){
ele.removeEventListener(type,callback,false);
}else if(ele.detachEvent){
       ele.detachEvent("on"+type,callback);
  }else{
       ele["on" + type] = null;
  }
}

在实际开发中,给父元素和子元素绑定事件的场景是很常见的。例:

 

思考:如何让事件不冒泡?

需要使用事件对象。

事件对象

浏览器为事件提供了一个对象,用来记录事件的各种具体信息,例如,鼠标点击的位置、鼠标按键的信息、键盘的键码。。。

这就是事件对象。

<body>
<button id="btn">按钮</button>
</body>
<script type="text/javascript">
btn.onclick=function(){
   console.log(window.event);
}
</script>

点击访问结果:

事件对象
1565841834616

从结果中可以看出,这个事件对象中包含了事件的类型、鼠标点击的位置,在屏幕中和在浏览器中的位置。点开的话,里面还有很多信息。

还有另外一种写法:

btn.onclick=function(e){
   console.log(e);
}

以前的时候,前面的写法是针对IE浏览器的,下面的写法是针对W3C标准浏览器的。上面的写法,现在基本都兼容了;下面这种写法,在IE低版本浏览器中还不兼容。

兼容所有浏览器的写法:

btn.onclick = function(e){
   var ev = e || window.event
   console.log(ev);
}

使用的是短路运算法。

var a = 1;
var b;
// 将赋值作为条件,永远是成立的
if(b=2){
   console.log(b); // 2
}
console.log(b); // 2

// 在或者的逻辑中,如果第一个条件为true,则不再执行第二个条件
if(a>0 || (b=3)){
   console.log(b); // 2
}
console.log(b); // 2

// 只有第一个条件是false的时候才会执行第二个条件
if(a>1 || (b=3)){
   console.log(b); // 2
}
console.log(b); // 2

// 逻辑运算符||两边都会转为布尔值进行判断
// 短路运算
var c = 0 || 1;
console.log(c); // 1
// 因为0转为布尔值是false,所以赋值的时候0没有执行

/* 相当于下面这几行代码 */
if(0){
c = 0;  
}else if(1){
c = 1;        
}else{
   c = undefined;
}

// 当e是false的时候,将window.event赋值给ev
ev = ev || window.event;

如果是行内绑定的事件,就将事件对象当做参数传进来即可。且必须是event。

例:

<button onclcik="fn(event)">
  按钮
</button>
<script>
   function fn(e){
       console.log(e);
  }
</script>

 

阻止事件冒泡

在事件对象中,有一个方法用来阻止事件冒泡,这个方法叫做stopPropagation。

例:

<body>
<style>
   #big{
       width: 200px;
       height: 200px;
       border:1px solid #000;
  }
   #middle{
       width: 150px;
       height: 150px;
       background: #abcdef;
  }
   #small{
       width: 100px;
       height: 100px;
       background: red;
  }
</style>
<div id="big">
  大盒子的内容
   <div id="middle">
      中盒子的内容
       <div id="small">
          小盒子的内容
       </div>
   </div>
</div>
</body>
<script type="text/javascript">
big.onclick=function(){
   console.log(this.innerText);
   console.log("大盒子的内容完毕");
}
middle.onclick=function(){
   console.log(this.innerText);
   console.log("中盒子的内容完毕");
}
small.onclick=function(e){
   var ev = e || window.event;
   ev.stopPropagation();
   console.log(this.innerText);
   console.log("小盒子的内容完毕");
}
</script>

此时,点击小盒子,不再触发父元素的事件。

阻止事件冒泡在IE浏览器中有兼容问题,在低版本IE浏览器中,需要使用另外一种写法:

ev.cancelBubble=true; # IE低版本浏览器

例:

small.onclick=function(e){
   var ev = e || window.event;
   ev.cancelBubble=true;
   console.log(this.innerText);
   console.log("小盒子的内容完毕");
}

为了兼容IE低版本浏览器,使用兼容写法:

small.onclick=function(e){
   console.log(this.innerText);
   console.log("小盒子的内容完毕");
   var ev = e || window.event;
   if(ev.stopPropagation){
  ev.stopPropagation
  }else{
       ev.cancelBubble=true;
  }
}

 

 

 

事件(下)

事件对象

在事件对象中记录了很多事件的信息。。。

事件类型

e.type // 事件的类型

例:

<button id="btn">
  按钮
</button>
<script>
   btn.onclick=function(e){
       var e = e || window.event;
       console.log(e.type); // MouseClick
  }
   btn.onmouseover=function(e){
       var e = e || window.event;
       console.log(e.type); // MouseOver
  }
</script>

 

鼠标按键信息

e.button // 鼠标按键的信息

0表示左键,1表示鼠标滚轮,2表示右键

<body>
<button id="btn">按钮</button>
</body>
<script type="text/javascript">
btn.onmousedown = function(e){
   var ev = e || window.event;
   var code = ev.button;
   if(code == 0){
      console.log("您点击的是左键");
  }else if(code == 1){
       console.log("您点击的滚轮");
  }else if(code == 2){
       console.log("您点击的是右键");
  }else{
       console.log("不知道你点击的是什么");
  }
}
</script>

按键键码

e.keyCode // 键盘的键码

常见的按键码:

  • 13: 回车键(enter)

  • 32: 空格键(space)

  • 数字和字母的键码是数字或字母对应的阿斯克码

<body>
<button id="btn">按钮</button>
</body>
<script type="text/javascript">
document.onkeypress=function(e){
   var ev = e || window.event;
   console.log(ev.keyCode);
}
</script>

作业:模拟打字游戏。

组合按键的判断:

  • altKey :alt 键按下得到 true,否则得到 false

  • shiftKey :shift 键按下得到 true,否则得到 false

  • ctrlKey :ctrl 键按下得到 true,否则得到 false

document.onkeyup = function (e) {
 e = e || window.event
 keyCode = e.keyCode || e.which
 
 if (e.shiftKey && keyCode === 97) {
   console.log('你同时按下了 shift 和 a')
}
}

使用说明:火狐firefox2.0和低版本IE中keyCode不兼容,可以使用e.which来获取

现在的低版本ie和火狐都能兼容keyCode

鼠标坐标点

从元素内部开始计算的坐标:offsetXoffsetY

<body>
<style>
#box{
   width: 200px;
   height: 200px;
   border: 1px solid #000;
}
</style>
<div id="box"></div>
</body>
<script type="text/javascript">
box.onclick = function(e){
   var ev = e || window.event;
   console.log(ev.offsetX,ev.offsetY);
}
</script>

访问结果:

元素内部的点击坐标
1565859316223

相对于浏览器的坐标,使用:clientXclientY

<body>
<style>
   #box{
       width: 200px;
       height: 200px;
       border: 1px solid #000;
       margin: 100px;
  }
</style>
<div id="box"></div>
</body>
<script type="text/javascript">
box.onclick = function(e){
   var ev = e || window.event;
   console.log(ev.clientX,ev.clientY);
}
</script>

访问结果:

相对于浏览器的坐标
1565860350842

使用说明:不管页面滚动到哪里,都是根据窗口来计算坐标。(不会随着滚动条的滚动而发生改变)

相对于页面的坐标,会随着滚动条的滚动而加大,使用:pageXpageY

<body>
<style>
   #box{
       width: 20px;
       border: 1px solid #000;
       margin: 100px;
  }
</style>
<div id="box">
      没有什么能够阻挡
      你对自由的向往
      天马行空的生涯
      你的心了无牵挂
      穿过幽暗的岁月
      也曾感到彷徨
      当你低头的瞬间
      才发觉脚下的路
      心中那自由的世界
      如此的清澈高远
      盛开着永不凋零
      蓝莲花
</div>
</body>
<script type="text/javascript">
box.onclick = function(e){
   var ev = e || window.event;
   console.log(ev.pageY);
}
</script>

访问结果:

 
1565860650579

横向坐标也是一样的。

拖拽效果

鼠标移动事件:mousemove

<body>
<style>
#box{
   width: 100px;
   height: 100px;
   background: pink;
   position:absolute;
   left:0;
   top:0;
}
</style>
<div id="box"></div>
</body>
<script type="text/javascript">
var x,y;
box.onmousedown=function(){
   this.onmousemove=function(e){
       var ev = e || window.event;
       x = ev.clientX - 50;
       y = ev.clientY - 50;
       if(x<0){
           x=0;
      }
       if(y<0){
           y=0;
      }
       // 屏幕宽度和屏幕高度
       var maxWidth = document.documentElement.clientWidth;
       var maxHeight = document.documentElement.clientHeight;
       // 能移动的最大宽度 = 屏幕宽度 - 盒子宽度
       var moveMaxWidth = maxWidth-100;
       var moveMaxHeight = maxHeight-100;
       if(x>moveMaxWidth){
           x = moveMaxWidth;
      }
       if(y>moveMaxHeight){
           y = moveMaxHeight;
      }
       this.style.left = x + "px";
       this.style.top = y + "px";
  }
}
box.onmouseup=function(){
  this.onmousemove=null;
}
</script>

注意:获取鼠标坐标位置的时候,不能使用offset来获取,因为offset获取到的值是鼠标在当前元素上的位置,也就是说一开始获取的是大盒子的位置,但是一旦设置了小盒子的位置,鼠标会出现在小盒子上,获取到的位置就成了鼠标在小盒子上的位置了

默认行为

具有默认行为的常见的两个标签

链接<a href="/index.php">点我</a>  往属性href指定的地址跳转
提交按钮<input type=”submit”>   往form表单属性action指定的地址跳转

阻止默认行为的方法:

  1. 给链接地址设置为javascript:;javascript:void(0)

  2. 在事件中最后return false

  3. 通过对象阻止,代码如下:

    function stopDefault(event) {
       var e = event || window.event;
       if (e.preventDefault){
           e.preventDefault();   // w3c标准浏览器
      }else{
           e.returnValue = false; // IE浏览器
      }
    }

鼠标右键也有默认行为。

事件委托

事件委托也叫事件代理(看站谁的角度),使用事件委托技术能避免对每个子节点添加事件监听,相反把事件监听委托给父元素即可,这样可提高绑定事件的性能。

传统的给每个元素绑定事件:

<ul>
<li>首页</li>
<li>公司介绍</li>
<li>产品中心</li>
</ul>
<script>
var oLis = document.getElementsByTagName("li"); // 获取到所有li
for(var i in oLis){
oLis[i].onclick = function(){
alert(this.innerText);
}
}
</script>

代码的缺点:

  1. li标签比较多的时候,性能特别差,毕竟使用for循环相当于绑定了多次

  2. 当动态给li添加元素的时候,新元素没有事件绑定

    ul>
    <li>首页</li>
    <li>公司介绍</li>
    <li>产品中心</li>
    </ul>
    <button id="btn">添加新元素</button>
    <script>
    btn.onclick = function(){
    var oNewLi = document.createElement("li");
    oNewLi.innerText = "新闻中心";
    var oUl = document.getElementsByTagName("ul")[0];
    oUl.appendChild(oNewLi)
    }
    var oLis = document.getElementsByTagName("li"); // 获取到所有li
    for(var i in oLis){
    oLis[i].onclick = function(){
    alert(this.innerText);
    }
    }
    </script>

    分析:当点击按钮给ul添加新元素以后,新元素不具备点击事件,点击没有效果

解决方案:使用事件委托,将所有子元素的点击事件委托给父元素

<ul>
<li>首页</li>
<li>公司介绍</li>
<li>产品中心</li>
</ul>
<button id="btn">添加新元素</button>
<script>
var oUl = document.getElementsByTagName("ul")[0];
btn.onclick = function(){
var oNewLi = document.createElement("li");
oNewLi.innerText = "新闻中心";
oUl.appendChild(oNewLi)
}
oUl.onclick = function(e){
var ev = e || window.event;
// 获取到单击的目标元素dom对象
var target = ev.target || ev.srcElement;
// 判断是否是li标签
if(target.nodeName == "li"){
// 完成业务逻辑
alert(target.innerText);
}
}
</script>

使用事件委托的好处:

  1. 提高性能(事件委托中并没有使用循环给每个节点设置事件,只给一个父元素ul绑定事件)

  2. 后续动态添加的节点也有事件的处理

注意:事件委托底层就是通过事件冒泡来完成的,先触发父元素的事件,在通过事件对象的target属性找到具体的目标元素,进而在处理目标元素要执行的业务逻辑。

事件对象总结

在行内绑定的事件,在行内传入event,其他事件驱动函数在定义的时候传入自定义参数。在函数中通过获取参数或者window.event来得到事件对象。

名称意义使用方式兼容问题
stopPropagation方法 阻止冒泡 e.propagation() e.cancelBubble=true
preventDefault方法 阻止默认行为 e.preventDefault() e.returnValue=false
clientX 鼠标点击坐标 e.clientX
offsetX 鼠标点击坐标 e.offsetX
pageX 鼠标点击坐标 e.pageX
target 精准的事件源 e.target e.srcElement
keyCode 键盘码 e.keyCode e.which
type 事件类型 e.type
button 鼠标按键信息 e.button



 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 总结

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 总结

 

 

 

 

 

 函数使用

 

循环判断

求素数

 

 

 去重

 

 

 

 

 

 基本类型与引用类型的区别

 

 

 

 

 

 选择排序

 

 

 Math.floor取整

 

 

 Math.abs相反数

 

 

 

 

 

 Math.sin角度

Math.PI  Π

正弦

 

BOM与DOM的介绍BOM与DOM的介绍

 

 

 

 

 

 

 window:object

总结

 

 

 

 前进

 

window.forward

 

 

 后退

window.back

 

 

 history

总结

 

 

 location(重要)

 

 解码和编码

 

 location(重要)三个属性

 

 

 

 location(重要)三个属性设置

三个方法

 

 总结

 

 window的弹出层

window一般情况下可省略

 

 

 

 

 

 总结

 

 

 

 window的事件

 

 滚动条事件

 

 

 

 定时器

 

 

 

 只实行一次的定时器

还能混用

 

 一般不混用

异步代码

与同步代码的区别

 

 

 

 在js中,异步代码,执行流程:

 

 html基本结构的操作

 

 标签的获取

 

 

 

 

 

 

 

 

 

 

 

 总结

 

 document.querySelector最常用  : 选择一个

document.querySelectorAll次常用  : 选择全部

内容操作

 

 

 

 

 

 jq22.com

设置样式

 

 两种方式即可

 

 设置类名

 

 补充

 

 

 

 

 

 

 

 标签的属性操作

 

 添加属性

 

 

 

 

 

 

总结

 

 属性操作

 

 

 

 总结

 

 节点的获取

 

 理解一下

重点是获取所以子标签的节点

 

 

 

 最后一个子节点

 

 

 

 只要是子标签都要记

 

 

 

 记

 

 

 

 

 

 

 

 节点的操作

 

 

 

 

 

 总结

 

 

 

 获取元素样式

 

 

 

 获取元素坐标

 

 获取元素的大小

 

 

 

 

 

 总结

 

 获取窗口大小

 

 获取滚动过的距离

 

 

 

 

 

 什么是短路

短路运算

 

 并且短路主要看右

 

 滚动条可赋值

 

 

 

 不能在unfinished上设置src属性

 

 

 

 事件复习

 

 更严谨用法

 

 鼠标按键事件

 

 解决兼容问题

 

 

 

 

 

 

 

 

 

 

 

 

 

 事件流

 

 

 

 事件绑定方式

 

 

 

 新语法新名称:事件侦听器/监听器

总结

 

 事件解绑

 

 

 

 总结

 

 事件对象

 

 不能添加实参,因为我们不知道小括号哪里定义

放形参的小括号失去作用了

 

 得出的对象叫做事件对象

 

 总结

 

 阻止事件冒泡

 

 以前阻止冒泡

 

 

 

 事件类型

 

 鼠标按键信息

 

 键盘的按键信息

 

 组合键

 

 总结

 

 

 

 获取鼠标点击的位置

 

 

 

 总结

 

 div在浏览器窗口的拖拽

 

 

 

 解绑

 

 总结

 

 默认行为

 

 第二种方式

 

 eturn必须放到函数的后面

第三种方法

 

 暴力方式

 

 

 

 鼠标右键菜单

 

 事件委托

 

 

 

 委托事件好处

1、提高了绑定效率

2、动态添加的新标签也可以具有事件

总结

 

mousedown只要是按鼠标键就能触发

 

 键盘事件要给能获取焦点的元素绑定:window document 表单元素

 

 数组塌陷

数组顺着删会在循环中跳过,会导致塌陷

 

 

es6

 

ES6

es6是ECMAScript的第6个版本,在2015年发布。也有的人将ECMAScript5之后版本,统称为es6。比起之前的语法,es6有很多新语法,让开发者在操作数据和函数的时候,功能既多,操作又简便。

数组新增的方法

  • some - 判断数组中是否至少有一个元素是满足指定条件的,返回布尔值

    语法:

    布尔值 = 数组.some(function(v,i,a){
       return 条件;
    })
    // 上面的i和a是可选参数

    例:判断所有成绩中是否有不及格的成绩

    var arr = [68,95,78,56,86,63];
    var bool = arr.some(function(v,i,a){
       return v<60;
    });
    console.log(bool); // true

    some内置的原理,遍历数组,判断每个值是否满足条件,有满足的就返回true,并break循环,遍历完以后都没有一个是满足的,返回false

    var arr = [68,95,78,56,86,63];
    var k = 0
    var bool = arr.some(function(v,i,a){
       k++
       return v<60;
    });
    console.log(bool); // true
    console.log(k); // 4

    var arr = [68,95,78,66,86,63];
    var k = 0
    var bool = arr.some(function(v,i,a){
       k++
       return v<60;
    });
    console.log(bool); // false
    console.log(k); // 6

     

  • every - 判断数组中是否所有元素都满足指定的条件,返回布尔值

    语法:

    布尔值 = 数组.every(function(){
       return 条件
    })
    // 上面的i和a是可选参数

    例:判断是否所有成绩都及格了

    var arr = [68,95,78,56,86,63];
    var bool = arr.some(function(v,i,a){
       return v>60;
    });
    console.log(bool); // false

    every内置的原理,遍历数组,判断每个值是否满足条件,有不满足的就返回false,并break循环,遍历完以后都满足,返回true

    var arr = [68,95,78,56,86,63];
    var k = 0
    var bool = arr.every(function(v,i,a){
       k++
       return v>60;
    });
    console.log(bool); // false
    console.log(k); // 4

    var arr = [68,95,78,66,86,63];
    var k = 0
    var bool = arr.every(function(v,i,a){
       k++
       return v>60;
    });
    console.log(bool); // true
    console.log(k); // 6

     

  • find - 查找数组中第一个满足指定条件的值,找到返回值,找不到返回undefined

    语法:

    = 数组.find(function(v,i,a){
       return 条件
    })
    // 上面的i和a是可选参数

    例:找出所有成绩中第一个不及格的成绩

    var arr = [68,95,78,56,86,63];
    var ele = arr.find(function(v,i,a){
       return v<60
    })
    console.log(ele); // 56

    find的原理,遍历数组,判断每个元素是否满足条件,满足就返回这个元素,并break循环,如果遍历完了都没有满足条件的,就返回undefined

    var arr = [68,95,78,56,55,86,63];
    var k = 0
    var ele = arr.find(function(v,i,a){
       k++
       return v<60;
    });
    console.log(ele); // 56
    console.log(k); // 4

    var arr = [68,95,78,66,86,63];
    var k = 0
    var ele = arr.find(function(v,i,a){
       k++
       return v<60;
    });
    console.log(ele); // undefined
    console.log(k); // 6

     

  • findIndex - 查找数组中满足条件的第一个对应的下标,找到返回下标,找不到返回-1

    语法:

    下标 = 数组.findIndex(function(v,i,a){
       return 条件
    })
    // 上面的i和a是可选参数

    例:找出所有成绩中第一个不及格的成绩的下标

    var arr = [68,95,78,56,86,63];
    var index = arr.find(function(v,i,a){
       return v<60
    })
    console.log(index); // 3

    findIndex的原理,遍历数组,判断每个元素是否满足条件,满足就返回这个元素的下标,并break循环,如果遍历完了都没有满足条件的,就返回-1

    var arr = [68,95,78,56,55,86,63];
    var k = 0
    var index = arr.find(function(v,i,a){
       k++
       return v<60;
    });
    console.log(index); // 3
    console.log(k); // 4

    var arr = [68,95,78,66,86,63];
    var k = 0
    var index = arr.find(function(v,i,a){
       k++
       return v<60;
    });
    console.log(index); // -1
    console.log(k); // 6

     

定义变量

es6中新增了两个类似于var的关键字来定义变量,分别是let和const。

var定义的变量,其实属于window的属性,平常直接输出变量名,是一种简写,完整的写法应该是window.变量名

var a = 10;
console.log(window)

1627019140986

let关键字

测试代码1:

let b = 10;
let b = 20;
console.log(b)

1566549154067

结论:let不允许重复定义变量

测试代码2:

console.log(b)
let b = 3;

1566549254628

结论:let定义的变量没有预解析

测试代码3:

let a = 10;
console.log(window.a)
console.log(window)

1627019604927

测试代码4:

for(let i=0;i<3;i++){
   
}
console.log(i)

1566549426372

结论:let定义的变量会自己创建一个块级作用域,将自己的作用域限制在大括号中。

总结:

let是声明变量的关键字,特点:

  1. 不允许重复声明

  2. 不存在预解析

  3. 在大括号中声明的变量只能在大括号中使用,如if、for的大括号中声明的变量

const关键字也是用来定义变量的,具备let的所有特性,另外,const定义的变量的值不能修改。

不能改变值
1566549613451

声明的时候必须赋值

声明的时候必须赋值
1566549756689

箭头函数

es6中的箭头函数是用来简写函数的

let fn = function(){
   console.log(111);
}

使用箭头函数简写

let fn = ()=>{console.log(111);}

带参数的写法:

let fn = function(a,b){
   console.log(a+b);
}

使用箭头函数改写

let fn = (a,b)=>{console.log(a+b);}

注意:如果只有一个形参的时候,小括号可以省略:

let fn = function(a){
   console.log(a);
}

使用箭头改写

let fn = a = > {console.log(a);}

注意:如果代码块中只有一行代码,箭头函数可以省略大括号,并将这行代码作为返回值

let fn = function(a){
   return a + 1;
}

箭头函数的写法

let fn = a = > a+1;

例:使用箭头函数定义一个返回m到n范围内的随机数的函数:

let fn = (m,n) => parseInt(Math.random()*(n-m+1))+m;

箭头函数使用注意事项:

  1. 箭头函数中的this比较混轮,所以在函数和方法中使用到this的时候,就不要用箭头函数

  2. 箭头函数中没有arguments

函数默认值

以前的函数不能有默认值,es6的函数中可以定义默认值:

function add(a,b=2){
   return a + b;
}
console.log(add(5));

可以用箭头函数改写:

let add = (a,b=2) => a+b;
console.log(add(5));

模板字符串

es6新增了定义字符串的方式,使用反引号

  1. 可以换行书写,保持字符串中的换行和空格

  2. 模板字符串中可以识别变量,使用美元符大括号:${变量}

解构赋值

解析一个数据结构并赋值,可以快速的从对象或数组中取出需要的内容,对象使用大括号,数组使用中括号

解构对象

之前从对象中取到内容的方式

let obj = {
   name:"张三",
   age:12,
   sex:"男",
}
let name = obj.name;
let age = obj.age;

解构的方式:

let obj = {
   name:"张三",
   age:12,
   sex:"男",
}
let {name} = obj;
/*
表示从obj中获取name属性,并赋值给声明的name变量
*/

使用说明:

  1. obj必须是一个对象

  2. obj中必须有name属性

还可以一次性解构多个变量:

let obj = {
   name:"张三",
   age:12,
   sex:"男",
}
let {name,age} = obj; // 声明并赋值了两个变量

可以将变量名换成一个别的名字:

let obj = {
   name:"张三",
   age:12,
   sex:"男",
}
let {name:username,age:a} = obj; // 将obj的name属性值赋值给username变量,age属性值赋值给变量a

多级解构:

let obj = {
   name:"张三",
   age:12,
   sex:"男",
   wife:{
       name:"翠花",
       age:11,
  }
}
let {wife} = obj;
let {name} = wife;
// 写为一行
let {wife:{name:wname}} = obj;

解构数组

let arr = [1,2,3];
let [num1] = arr; // 从数组中拿出第一个元素赋值给num1变量

使用说明:

解构数组的时候是按顺序取出数组中的值,解构一个变量,只能拿到第一个元素

解构多个元素:

let arr = [1,2,3];
let [num1,num2] = arr; // num1 = arr[0]   num2 = arr[1]

多维数组解构:

let arr = [1,2,3,[4,5,6]];
let [a,b,c,[aa,bb]] = arr;
console.log(aa,bb); // 4 5

利用结构交换两个变量的值:

let num1 = 1;
let num2 = 2;
[num2,num1] = [num1,num2]

 

展开运算符

将一个数组展开为多个变量赋值给多个形参

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

利用展开运算求数组的最大值

let arr = [5,3,6,9,8,1,7];
let max = Math.max(...arr);
console.log(max); // 9

利用展开运算合并数组

// 之前的写法
let arr = [1,2,3];
let arr1 = [4,5,6].concat(arr);
// 利用展开运算合并
let arr2 = [4,5,6].concat(...arr);
// 再简化
let arr3 = [4,5,6,...arr]

利用展开运算合并对象:

const obj = {
   name:"Jack",
   age:20,
   sex:"男",
}
const obj1 = {
   ...obj,
   wife:{
       name:"Rose",
       age:18
  }
}
console.log(obj1);

合并运算符

将多个实参合并为一个数组

function fn(...arr){
   console.log(arr);
}
fn(1,2,3); // [1,2,3]

箭头函数中没有arguments,可以使用合并运算符来模拟arguments

var fn = (...arr) => {console.log(arr)};
fn(1,2,3); // [1,2,3]

对象的简写方式

let name = '张三';
let age = 12;
let obj = {
   name,
   age
}
console.log(obj);

如果对象的属性名和变量名同名,则可以光写属性名

字符串语法

  1. startsWith() 是否以谁开头,返回布尔值

    let str1 = "file:///C:/Users/iTAze/Desktop/1.html";
    let str2 = "https://mp.csdn.net/postedit";
    console.log(str1.startsWith("https://"))// false;
    console.log(str1.startsWith("file:///"))// true;
  2. endsWith() 是否以谁结尾,返回布尔值

  3. includes() 判断一个字符串或数组是否包含一个指定的值

    'Blue Whale'.includes('blue'); // return false

 

其他补充

检测数据类型

之前使用typeof检测数据类型,但这种方式只能检测基本数据类型。在判断数组或对象的时候不能准确判断。

有一个比较长的方法,可以检测所有数据类型:

Object.prototype.toString.call(被检测的数据类型)

例:

console.log(Object.prototype.toString.call(123));
console.log(Object.prototype.toString.call('abc'));
console.log(Object.prototype.toString.call(true));
console.log(Object.prototype.toString.call(undefined));
console.log(Object.prototype.toString.call(null));
console.log(Object.prototype.toString.call([]));
console.log(Object.prototype.toString.call({}));
console.log(Object.prototype.toString.call(function(){}));
console.log(Object.prototype.toString.call(/^abc$/));
console.log(Object.prototype.toString.call(new Date()));

访问结果:

检测数据类型
1566553259569

this 关键字

每个函数内容都有一个关键字叫做this。不同的情况下,this代表的内容也是不一样的。

  1. 全局中的this代表window

    console.log(this)

     

  2. 普通函数中的this代表window对象

    function fn(){
       console.log(this);
    }
    fn(); // window

     

  3. 定时器中的this代表window

    var obj = {
       eat:function(){
           setTimeout(function(){
               console.log(this);
          });
      }
    };
    obj.eat(); // window

     

  4. 自调用函数中的this代表window

    document.querySelector("button").onclick=function(){
      (function(){
           console.log(this);
      })()
    }
    // window

     

  5. 对象方法中的this代表调用这个方法的对象

    var obj = {
       eat:function(){
           console.log(this);
      }
    };
    obj.eat(); // obj

     

  6. 事件函数中的this代表当前事件的事件源

    document.querySelector("button").onclick=function(){
       console.log(this);
    }
    // <button>按钮</button>

     

  7. 箭头函数的this在定义箭头函数的时候就知道了,代表上一行代码的this

    document.querySelector("button").onclick=function(){
       // 这里的this代表button按钮,所以箭头函数的this也是button按钮
       setTimeout(()=>{console.log(this);});
    }
    // <button>按钮</button>

     

重点:函数内部的 this 只和函数的调用方式有关系,和函数的定义方式没有关系。箭头函数在定义的时候就知道this代表什么

上下文调用模式

也叫作方法借用模式。任何函数都能调用call、apply、bind这三个方法。这三个方法主要用于改变函数中this的指向。

call

call方法也可以用来调用函数:

function fn1(){
   console.log(123);
}
// fn1();
fn1.call(); // 使用call方法调用函数和小括号调用时一样的

call方法不仅可以用来调用函数,还可以指定调用函数的this指向。call的第一个参数就可以改变函数内的this指向:

function fn2(){
   console.log(this);
}
fn2.call([1,2,3]); // 打印结果就是这个数组

这时候的this就变成了call的第一个参数,也就是这个数组

call的参数可以有若干个,第一个参数用来改变函数内的this指向,其余的函数是作为调用函数的实参

function fn3(num1,num2){
   console.log(this);
   console.log(num1+num2);
}

// fn3(10,20);
var arr = [10,20];
fn3.call(arr,arr[0],arr[1]); //结果: Array 30

如果call没有参数或第一个参数为null,那么函数中的this执行window

function fn4(){
   console.log(this);
}
fn4.call(); // window
fn4.call(null); // window
fn4.call(undefined); // window

apply

apply的作用和call是一样的,区别只在于写法,apply只有两个参数,第二个参数是一个数组或者伪数组

function fn5(num1,num2){
   console.log(this);
   console.log(num1+num2);
}
var arr = [10,20];
fn5.apply(null,arr); // window 30

apply的特性: apply的平铺性: 将数组的中每一项取出来,作为借用函数的实参

什么时候用什么方法(call、apply)

  1. 如果参数比较少的情况下,使用call比较方便

  2. 如果参数已经存放在数组中,使用apply

bind

语法:var fn2 = fn.bind(thisArg);

作用: bind会创建并返回一个新的函数, 新的函数和借用的函数是一模一样的, 但是新函数内的this已经被改变成了bind的参数thisArg

function fn6(){
   console.log(this);
}
fn6(); // window
var arr = [1,2,3];
var fn7 = fn6.bind(arr);
fn7(); // Array(1,2,3)
console.log(fn6,fn7);

结果:

bind
1566124874331

bind 是不会去调用fn函数的,不像call、apply会去调用函数。bind会创建并返回一个新的函数,和借用的函数是一模一样的,但是新函数内部的this变成了指定的对象

使用场景:经常用于将定时器的this(window)变成指定的对象:

var obj = {
   name:'张三',
   lover:'李四',
   sayLove:function(){
       // 使用bind将属于window的setTimeout变成当前对象的setTimeout
       setTimeout(function(){
           console.log(this.name+"爱"+this.lover);
      }.bind(this),500);
  }
}
obj.sayLove(); // 张三爱李四

如果没有bind的话,打印结果是:""爱undefined

json

json对象

js中的数组或者对象都可以是json对象

json字符串

json格式的字符串叫做json字符串

字符串和对象的转换

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

var obj = {
   "name":"张三",
   "age":12
}
var str = JSON.stringify(obj);
console.log(str); // {"name":"张三","age":12} 这是个字符串

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

var str = '{"name":"张三","age":12}';
var obj = JSON.parse(str);
console.log(obj); // {"name":"张三","age":12} 这是个对象

伪数组

伪数组是一个对象。

这个对象中必须有length属性,如果length不为0,那么这个对象中必须有下标和对应的数据。

var farr = {
   0:123;
   length:1;
}

这就是伪数组。

常见的伪数组有:

arguments
DOM对象列表----HTMLCollection

伪数组转为数组的方法:

Array.prototype.slice.call(fakeArray) 

也可以进行遍历放入数组中。

伪数组和数组的对比
1566559392979


ES6

以升级为强弱型语言

全是重点

es6中的变量

错误信息

 

 

 

 

 

 块级作用域

 

 

 

 可以重复赋值

错误信息

 

 let 在自己的作用域中,所以不在window上

const用法几乎和let相似,只有一个区别

 

 const的值是不能修改的,一旦定义就不能改变,也称常量

总结

 

 

 

 

 

 es6中的函数

 

 

 

 注意:只能简化简单的匿名函数

 

 

 

 

 

 

 

 

 

 es6中的字符串

 

 

 

 重点

总结

 

 字符串方法

 

 

 

 es6新增数组方法

 

 

 

 every很常用

 

 find找不到就返回underf

 

 解构赋值

 

 多重解构

 

 

 

 最快交换两个变量的值

 

解构时变量名必须跟对象的键值对保持一致

键的名字

 

 

 

 定义中有中括号或者大括号,就是解构

点点点运算符

 

 

 

 

 

 

 

 

 获取地址栏的数据

 

 

 

 

 

 

 总结:

 

 文档碎片

 

 

节点复习

 ES6补充语法

简写对象

 

权重补充

 

   

 

 

 

 

posted on 2022-03-26 17:28  金子fa  阅读(101)  评论(0编辑  收藏  举报