js“字典”

闲话

根据记忆曲线,#¥……&……@,反正不经常复习使用,忘记一个东西就很快,所有,在这写一个js知识列表,方便自己复习。

该列表和廖雪峰老师的教程目录一样,非常感谢廖雪峰老师提供这么好的教程。

基础

  • 基本语法

    • 四格缩进
    • 注释使用//, 多行/* */
  • 数据类型和运算符

    • Number

    • 布尔值

    • string

      • 转义字符(反斜杠)

      • 多行字符

      • 字符串连接及模板字符

        1
        2
        3
        4
        var name = '小明';
        var age = 20;
        var message = `你好, ${name}, 你今年${age}岁了!`;
        alert(message);
      • 字符串操作

        • 索引取值/length获取长度
        • toUpperCase, toLowerCase, indexOf, subString
    • 数组

      • length取得Array的长度
      • 可以通过索引把对应的元素修改为新的值
      • 且如果通过索引赋值时,索引超过了范围,同样会引起Array大小的变化
      • indexOf, slice, push/pop, unshift/shift, sort, reverse, splice, concat, join
      • 多维数组
    • 对象

      • 命名和调用
      • 检测对象是否拥有某一属性,可以用in操作符
        1
        2
        3
        4
        5
        6
        var xiaoming = {
        name: '小明',
        birth: 1990
        };
        'name' in xiaoming; // true
        'grade' in xiaoming; // false
    • 逻辑运算符

    • 比较运算符

    • null: null表示一个“空”的值,它和0以及空字符串’’不同,0是一个数值,’’表示长度为0的字符串,而null表示“空”

    • undefined: 表示“未定义”

      • 区分两者的意义不大。大多数情况下,我们都应该用null。undefined仅仅在判断函数参数是否传递的情况下有用。
  • 条件判断

  • 循环

    • for/while/do{}while
    • for (… in …)
      • 把一个对象的属性依此循环出来,也可以是数组(循环出index)
  • Map&Set

    • Map是一组键值对的结构,具有几块的查找速度

      • 创建

        • new Map(二维数组/或空)

          1
          var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
        • 常见使用

          1
          2
          3
          4
          5
          6
          7
          var m = new Map(); // 空Map
          m.set('Adam', 67); // 添加新的key-value
          m.set('Bob', 59);
          m.has('Adam'); // 是否存在key 'Adam': true
          m.get('Adam'); // 67
          m.delete('Adam'); // 删除key 'Adam'
          m.get('Adam'); // undefined
    • set和map类似,但是一组key的组合

      • 不能更改,只能add()和delete()
      • 创建
        • new Set(一维数组/或空)
  • iterable

    • 可迭代对象,Array,Map,Set均为iterable类型
    • for (.. of ..)
    • forEach()
      1
      2
      3
      4
      var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
      m.forEach(function (value, key, map) {
      console.log(value);
      });

函数

  • 函数的定义与调用

    • 额外参数arguments,指向函数调用者传入的所有参数

      • 最常用于判断传入参数的个数
    • rest参数只能写在最后,前面用…标识,从运行结果可知,传入的参数先绑定a、b,多余的参数以数组形式交给变量rest;如果传入的参数连正常定义的参数都没填满,也不要紧,rest参数会接收一个空数组(注意不是undefined)

      1
      2
      3
      4
      5
      function foo(a, b, ...rest) {
      console.log('a = ' + a);
      console.log('b = ' + b);
      console.log(rest);
      }
    • JavaScript引擎有一个在行末自动添加分号的机制,这可能让你栽到return语句的一个大坑

  • 变量作用域和解构赋值

    • 查找变量机制
    • 变量提升
    • 全局作用域
    • 名字空间(解决不同文件相同全局变量的命名冲突)
    • 局部作用域
      • var 作用域,函数内部
      • let for循环等语句块
    • 常量const
      • 可以进行赋值,但是不会生效
    • 解构赋值
      • 嵌套层次和位置
      • 将变量名变化和对应属性名不一致(用冒号)
      • 若属性不存在,会得到undefined,可以通过赋初值来解决(用等号)
      • 对已声明变量的赋值(用括号包裹)
      • 应用
        • 对象的快速赋值
        • 函数传参
  • 方法

    对象中绑定函数,称为该对象的方法

    重点: this关键字的指向

    • apply()或call()控制this指向
    • 装饰器
  • 高阶函数

    • map()

      map方法,传入一个函数,然后作用在调用map的数组中每个元素上,并返回一个新的数组

    • reduce()

      Array的reduce()把一个函数作用在这个Array的[x1, x2, x3…]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是:

      1
      [x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
    • filter()

      filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。

      Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。

      filter()接收的回调函数,其实可以有多个参数。通常我们仅使用第一个参数,表示Array的某个元素。回调函数还可以接收另外两个参数,表示元素的位置和数组本身

    • sort()

      • 可传入自定义排序函数
      • 坑: Array的sort()方法默认把所有元素先转换为String再排序!!!
  • 闭包

    我们在函数parent中又定义了函数child,并且,内部函数child可以引用外部函数parent的参数和局部变量,当parent返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。

    特性: 实现了状态的保存和隐藏

  • 箭头函数

    不仅是匿名函数的一种简写,还有一个明显的区别————this

  • generator

    生成器,与python中generator的概念和语法比较想象

标准对象

  • Date

    再JavaScript中,用Date对象来表示日期和时间

    • 获取当前系统时间
    • 如果要创建一个指定日期和时间的Date对象
      • 可以传入三种格式
    • 易错: 月份0-11
  • RegExp

  • JSON

    • JSON的字符串规定必须用双引号””,Object的键也必须用双引号””
    • 对象序列化成一个JSON格式的字符串
      • 格式化
      • 精确控制如何序列化对象
    • 将JSON格式的字符串,只需要把它反序列化成一个JavaScript对象

面向对象的编程

  • class的使用及继承

    • 通过改变原型创建

      JavaScript的原型链和Java的Class区别就在,它没有“Class”的概念,所有对象都是实例,所谓继承关系不过是把一个对象的原型指向另一个对象而已。

      当我们用obj.xxx访问一个对象的属性时,JavaScript引擎先在当前对象上查找该属性,如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到Object.prototype对象,最后,如果还没有找到,就只能返回undefined。

    • 新的关键字class从ES6开始正式被引入到JavaScript中。class的目的就是让定义类更简单。

      和C语言的类定义方法和继承方法相近

      示例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      // Student类
      class Student {
      constructor(name) {
      this.name = name;
      }

      hello() {
      alert('Hello, ' + this.name + '!');
      }
      }

      // PrimaryStudent子类
      class PrimaryStudent extends Student {
      constructor(name, grade) {
      super(name); // 记得用super调用父类的构造方法!
      this.grade = grade;
      }

      myGrade() {
      alert('I am at grade ' + this.grade);
      }
      }

      ps: 下面两部分内容是ES6前要实现对象模型的方法,当然现在使用class更加方便,但下两话题,对理解原型很有帮助。

  • 创建对象

    • JavaScript对每个创建的对象都会设置一个原型,指向它的原型对象。
      • 原型链
        • 对象的原型链
        • 函数的原型链
      • 构造函数
        • 定义时为普通的函数定义,调用时用关键字new来调用这个函数,并返回一个对象
        • 构造函数的原型链(重要概念constructor,prototype)
        • 如何共享一个方法,有点是什么
  • 原型继承

    • JavaScript的原型继承实现方式就是:

      1. 定义新的构造函数,并在内部用call()调用希望“继承”的构造函数,并绑定this;
      2. 借助中间函数F实现原型链继承,最好通过封装的inherits函数完成;
      3. 继续在新的构造函数的原型上定义新方法。

浏览器

浏览器对象

  • window

    window对象不但充当全局作用域,而且表示浏览器窗口。

    • 具有innerWidth/innerHeight属性,可以获取浏览器窗口的内部宽度和高度。内部宽高是指除去菜单栏、工具栏、边框等占位元素后,用于显示网页的净宽高。
    • 也有outerWidth/outerHeight属性,可以获取浏览器窗口的整个宽高
  • navigator对象表示浏览器的信息,常用属性有:

    • navigator.appName:浏览器名称;
    • navigator.appVersion:浏览器版本;
    • navigator.language:浏览器设置的语言;
    • navigator.platform:操作系统类型;
    • navigator.userAgent:浏览器设定的User-Agent字符串。
      1
      2
      3
      4
      // 提到短路运算符
      // 充分利用JavaScript对不存在属性返回undefined的特性,直接用 **短路运算符||** 计算

      var width = window.innerWidth || document.body.clientWidth;
  • screen

    screen对象表示访问者 屏幕 的信息,常见属性有:

    • screen.width
    • screen.height
    • screen.colorDepth
  • location

    location对象表示当前页面的URL信息。

    常用属性和方法:

    • href,protocol,host,port,pathname,search,hash
    • assign() 加载一个新页面
    • reload() 重新加载当前页面
  • document💎

    document对象表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构,document对象就是整个DOM树的根节点。

  • history

    history对象保存了浏览器的历史记录,JavaScript可以调用history对象的back()或forward (),相当于用户点击了浏览器的“后退”或“前进”按钮。这个对象属于历史遗留对象,对于现代Web页面来说,由于大量使用AJAX和页面交互,简单粗暴地调用history.back()可能会让用户感到非常愤怒。

    新手开始设计Web页面时喜欢在登录页登录成功时调用history.back(),试图回到登录前的页面。这是一种错误的方法。

    任何情况,你都不应该使用history这个对象了。

操作DOM

  • 获取DOM节点

    • 获取已存在的DOM节点,document对象提供的getElementById()和getElementsByTagName()可以按ID获得一个DOM节点和按Tag名称获得一组DOM节点
    • 创建一个DOM节点(如: var div1 = document.createElement(‘div’);)
  • 更新DOM

    • 修改节点的文本,方法有两种

      • 一种是修改innerHTML属性

        1
        2
        3
        var p = document.getElementById('p-id');
        p.innerHTML = 'ABC';
        p.innerHTML = 'ABC <span style="color:red">RED</span> XYZ';

        用innerHTML时要注意,是否需要写入HTML。如果写入的字符串是通过网络拿到了,要注意对字符编码来避免XSS攻击。

    • 第二种是修改innerText或textContent属性,这样可以自动对字符串进行HTML编码,保证无法设置任何HTML标签

      1
      2
      3
      4
      5
      6
      // 获取<p id="p-id">...</p>
      var p = document.getElementById('p-id');
      // 设置文本:
      p.innerText = '<script>alert("Hi")</script>';
      // HTML被自动编码,无法设置一个<script>节点:
      // <p id="p-id">&lt;script&gt;alert("Hi")&lt;/script&gt;</p>
      • innerText和textContent的区别在于,读取属性时,innerText不返回隐藏元素的文本,而textContent返回所有文本。
    • 修改样式

      • DOM节点的style属性对应所有的CSS,可以直接获取或设置。因为CSS允许font-size这样的名称,但它并非JavaScript有效的属性名,所以需要在JavaScript中改写为驼峰式命名fontSize
        1
        2
        3
        4
        5
        6
        // 获取<p id="p-id">...</p>
        var p = document.getElementById('p-id');
        // 设置CSS:
        p.style.color = '#ff0000';
        p.style.fontSize = '20px';
        p.style.paddingTop = '2em';
    • 添加id, class等属性,都是通过p.id=’xx’这种形式

  • 插入DOM

    • 若这个DOM节点为空(如:

      ),那么,直接使用innerHTML = ‘child‘就可以修改DOM节点的内容,相当于“插入”了新的DOM节点。

    • 若该节点不为空

      • appendChild(),,把一个子节点添加到父节点的最后

        • 如果我们要插入的js节点已经存在于当前的文档树,因此这个节点首先会从原先的位置删除,再插入到新的位置。
        • 当然,更多时候是插入一个我们新建的节点
          1
          2
          3
          4
          5
          var list = document.getElementById('list'),
          var haskell = document.createElement('p');
          haskell.id = 'haskell';
          haskell.innerText = 'Haskell';
          list.appendChild(haskell);
      • insertBefore(newElement, referenceElement), 可以把子节点插入到指定的位置referenceElement之前

        • 可见,使用insertBefore重点是要拿到一个“参考子节点”的引用。很多时候,需要循环一个父节点的所有子节点,可以通过迭代children属性实现:
          1
          2
          3
          4
          5
          6
          var
          i, c,
          list = document.getElementById('list');
          for (i = 0; i < list.children.length; i++) {
          c = list.children[i]; // 拿到第i个子节点
          }
    • 动态创建一个节点然后添加到DOM树中,可以实现很多功能。举个例子,下面的代码动态创建了一个style节点,然后把它添加到< head>节点的末尾,这样就动态地给文档添加了新的CSS定义

      1
      2
      3
      4
      var d = document.createElement('style');
      d.setAttribute('type', 'text/css');
      d.innerHTML = 'p { color: red }';
      document.getElementsByTagName('head')[0].appendChild(d);
  • 删除DOM

    • 要删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild把自己删掉。
    • 注意到删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置。

操作表单

  • 获取值value/checked

  • 设置值(直接对相应DOM节点赋值)

  • HTML5控件

    • HTML5新增了大量标准控件,常用的包括date、datetime、datetime-local、color等,它们都使用< input>标签
  • 提交表单

    • 一般都是通过响应< form>本身的onsubmit事件,浏览器还会根据onsubmit()的返回值,return true来告诉浏览器继续提交,如果return false,浏览器将不会继续提交form,这种情况通常对应用户输入有误,提示用户错误信息后终止提交form。

操作文件

  • 在HTML表单中,可以上传文件的唯一控件就是<input type="file">
    • 注意: 当一个表单包含<input type="file">时,表单的enctype必须指定为multipart/form-data,method必须指定为post,浏览器才能正确编码并以multipart/form-data格式发送表单的数据。
    • 出于安全考虑,浏览器只允许用户点击<input type="file">来选择本地文件; 当用户选择了上传某个文件后,JavaScript也无法获得该文件的真实路径。
    • JavaScript可以在提交表单时对文件扩展名做检查,以便防止用户上传无效格式的文件
  • 随着HTML5的普及,新增的File API允许JavaScript读取文件内容,获得更多的文件信息。