> 文章列表 > JavaScript学习笔记(一)

JavaScript学习笔记(一)

JavaScript学习笔记(一)

文章目录

    • 第1章:什么是JavaScript
      • 1. JavaScript实现
      • 2. ECMAScript
      • 3. DOM
      • 4. BOM
    • 第2章:HTML中的JavaScript
      • 1.\\<Script\\>元素
      • 2.行内代码于外部文件
      • 3.文档模式
      • 4.\\<noscript\\>元素
    • 第3章 语言基础
      • 1.语法
      • 2.关键字与保留字
      • 3.变量
      • 4.数据类型
      • 5.操作
      • 6.语句
      • 7.函数

第1章:什么是JavaScript

1. JavaScript实现

  1. 核心(ECMAScript):由ECMA-262定义并提供核心功能
  2. 文档对象模型(DOM):提供与网页内容交互的方法和接口
  3. 浏览器对象模型(BOM):提供与浏览器交互的方法和接口

2. ECMAScript

  1. ECMA-262定义的一种语言基准,在此基础上构建更稳健的脚本语言
  2. Web浏览器只是ECMAScript实现的一种宿主环境(host environment),Node.js是服务器端JavaScript平台,也是一种宿主环境。
  3. ECMA-262定义了:语法,类型,语句,关键字,保留字,操作符,全局对象

3. DOM

  1. 文档对象模型,Document Object Model,是API。
  2. DOM将页面抽象为一组分层节点,创建表示文档的树。

4. BOM

  1. 浏览器对象模型,也是API。
  2. 通常把任何特定于浏览器的扩展都归在BOM的范畴内。
  3. 没有标准,HTML5之后,BOM实现细节日趋一致。

第2章:HTML中的JavaScript

1.<Script>元素

  1. 将JavaScript插入HTML的主要方法是使用<script>元素
  2. 是HTML规范
  3. <script>元素有8个属性
    • async:可选。立即开始下载脚本,但不阻止其他页面动作,异步。
    • charset:可选。使用src属性指定的代码字符集,很少用,因为大多数浏览器不care它的值。
    • crossorigin:可选。配置相关请求的CORS(跨资源共享)设置,默认不使用CORS。
    • defer:可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。
    • integrity:可选。用于确保内容分发网络(CDN,Content Delivery Network)不会提供恶意内容。
    • language:废弃。
    • src:可选。表示包含要执行的代码的外部文件的URL,可以跟网页在同一台服务器上,也可以位于完全不同的域。
    • type:可选。代替language,表示代码块中脚本语言的内容类型(也称MIME类型)。例:“text/javascript”
  4. 使用方式
    • 网页中嵌入JavaScript代码
    • 在网页中包含JavaScript文件
  5. 使用了src属性的<script>元素不应该再在<script>和</script>标签中再包含其他JavaScript代码。如果两者都提供的话,浏览器只会下载并执行脚本文件,忽略行内代码。
  6. 建议将JavaScript引用放在<body>元素中的页面内容后面,因为页面在浏览器解析到<body>的起始标签时开始渲染,放在前面会导致页面渲染的明显延迟。
  7. 推迟执行脚本:defer属性。该属性只对外部脚本文件有效。HTML5规范要求脚本应该按照出现顺序执行,所以第一个defer的脚本会在第二个defer的脚本之前执行。但实际上不一定,so最好只包含一个defer脚本。因为有的浏览器会忽略这个属性,所以还是把要推迟执行的脚本放在页面底部比较好。
  8. 异步执行脚本:async属性。也只适用于外部脚本。但是标记为async的脚本不能保证按照出现次序执行,因为它们之间没有依赖关系。
  9. 动态加在脚本:使用DOM API,通过向DOM中动态添加script元素加载指定的脚本。只要创建一个script元素并将其添加到DOM即可。这种方式以异步加载,相当于添加了async属性,但是不是所有的浏览器都支持这个属性,所以可以将其设置为同步加载。
    let script =document.createElemnet('script')`` script.src='gibberish.js' script.async = false; // 设置为同步加载 document.head.apendChild(script)
    这种方式获取的资源对浏览器的预加载器不可见,严重影响性能。要想让预加载器知道动态请求文件的存在,可以在文档头部显式声明它们:
    <link rel="preload" href="gibberish.js">
  10. XHTML中的变化:XHTML中使用JavaScript必须指定type属性且值为text/javascript。XHTML模式会在页面的MIME类型被指定为"application/xhtml+xml"时触发。

2.行内代码于外部文件

  1. 推荐使用外部文件,理由如下
    • 可维护性。用一个目录保存所有的js文件,更容易维护,开发者可以独立于使用它们的HTML页面来编辑代码。
    • 缓存。浏览器会根据特定的设置缓存所有外部链接的js文件,所以如果两个页面都用到同一个文件,只需要下载一次,从而使页面加载更快。
    • 适应未来。包含外部js文件的语法在HTML和XHTML中一样。

3.文档模式

  1. 使用doctype切换文档模式
    • 混杂模式(quirks mode):省略文档开头的doctype声明
    • 标准模式(standards mode)
    • 准标准模式(almost standards mode)

4.<noscript>元素

  1. 用于给不支持js的浏览器提供替代内容。
  2. 如今的浏览器已经100%支持js
  3. 对于禁用js的浏览器来说,这个元素有用

第3章 语言基础

1.语法

  1. 区分大小写
  2. 标识符:
    • 可以由一个或多个字符组成,第一个字符必须是一个字母,下划线(_)或美元符号($),剩下的其他字符可以是字母、下划线、美元符号或数字。
    • 按照惯例使用驼峰大小写形式,不是强制性的。
    • 关键字、保留字、true、false和null不能作为标识符。
  3. 注释:
    • 单行注释:// 注释内容
    • 多行注释:/* 注释内容 */
  4. 严格模式(strict mode):
    • "use strict"启用严格模式,可以对整个脚本启用,也可以对指定函数启用,这是一个预处理指令。
    • 所有现代浏览器都支持严格模式。
  5. 语句
    • 以分号结尾,没有分号意味着由解析器确定语句在哪结尾,也有效,但不推荐。
    • 多条语句可以合并到一个代码块中,代码块由 ‘{’ 标识开始,'}'标识结束。
    • if之类的控制语句只在执行多条语句时要求必须有代码块,但推荐加代码块,减少出错。

2.关键字与保留字

  1. 关键字
    JavaScript学习笔记(一)
  2. 保留字
    JavaScript学习笔记(一)

3.变量

  1. var关键字
    • 可以保存任何类型的值,没有初始化的情况下保存一个特殊值undefined
    • 可以同时定义变量并设置它的值
    • 可以改变保存的值,也可以改变值的类型
    • var声明作用域:在函数内部定义的变量只在函数内部有效,在函数内定义变量时省略var操作符,可以创建一个全局变量,但不推荐这么做。
    • 定义多个变量可以在一条语句中用逗号分隔
    • var声明提升:var声明的变量会自动提升到函数作用域顶部
    • 反复使用var声明同一个变量也没有问题
  2. let声明
    • let声明的范围是块作用域,而var声明的范围是函数作用域,块作用域是函数作用域的子集
    • let不允许同一个块作用域中出现冗余声明
    • 暂时性死区:let与var的一个重要区别是,let声明的变量不会在作用域中被提升。let声明之前的执行瞬间被称为“暂时性死区”(temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出ReferenceError。
    • 全局声明:let在全局作用域中声明的变量不会成为window对象的属性(var声明的变量会)。
    • 条件声明:不能使用let进行条件式声明(条件声明是一种反模式)
    • for循环中的let声明:使用let声明for循环中的迭代变量,则变量的作用域仅限于for循环块内部,不会出现渗透到循环体外部的情况。
  3. const声明
    • 声明变量时必须同时初始化变量。
    • 尝试修改const声明的变量会导致运行时错误。不能声明迭代变量。
    • 不允许重复声明。
    • 声明的作用域也是块。
    • const声明的限制只适用于它指向的变量的引用,可以修改这个对象内部的属性。
  4. 声明风格及最佳实践
    • 不使用var
    • const优先,let次之

4.数据类型

  1. 简单数据类型:Undefined、Null、Boolean、Number、String和Symbol。
  2. 复杂数据类型:Object
  3. typeof操作符:用来确定变量的数据类型,只是一个操作符,不是函数,不需要参数(当然也可以使用参数)
  4. Undefined类型:
    • 只有一个值,就是特殊值undefined。
    • 当var和let声明了变量但是没有初始化时,默认给变量赋值undefined。
    • 不必显式地将变量值设置为undefined。
  5. 注意:无论是声明后未赋值还是未声明,typeof返回的都是"undefined",逻辑上是对的。建议在声明变量的同时初始化,这样当typeof返回"undefined"的时候就知道是未声明而不是声明了但未初始化。
  6. Null类型:
    • 只有一个值,特殊值null。表示一个空对象指针。
    • 当一个变量要保存对象而又没有对象可保存时,将变量显式的赋值为null。
  7. 注意:用比较操作符(==)比较null和undefined始终返回true。
  8. Boolean类型:
    • 有两个字面值:true,false
    • Boolean()转型函数:将其他类型的值转换为布尔值
      JavaScript学习笔记(一)
  9. Number类型
    • 八进制:第一位必须为0,严格模式下无效。应该使用前缀0o
    • 十六进制:前缀0x。
    • 浮点值:
      • 数值中必须包含小数点,小数点后面必须至少有一个数字。小数点前不是必须有整数,但推荐加上。
      • 科学计数法表示:一个数值(整数或浮点数)后跟一个大写或小写的字母e,再加上一个要乘的10的多少次幂。例:3.125e7,3e-17。
    • 值的范围:
      • 最小值:Number.MIN_VALUE,大概是5e-324。
      • 最大值:Number.MAX_VALUE,大概是1.797 693 134 862 315 7e+308。
      • 任何无法表示的负数:-Infinity(负无穷大),Number.NEGATIVE_INFINITY
      • 任何无法表示的正数:Infinity(正无穷大),Number.POSITIVE_INFINITY
      • 如果计算返回正 Infinity 或负 Infinity,则该值将不能再进一步用于任何计算。
      • isFinite()函数:用于确定一个数是不是有限大。
    • NaN
      • 不是数值,not a number。用于表示本来要返回数值的操作失败了。
      • 任何涉及NaN的操作始终返回NaN。
      • NaN不等于包括NaN在内的任何值。
      • isNaN()函数:接受一个参数,判断该参数是否“不是数值”。
    • 数值转换:有三个函数可以将非数值转换为数值
      • Number():可用于任何数据类型。
      • parseInt():主要用于将字符串转换为数值。可以接收两个参数,第二个参数表示底数(进制数)。建议给第二个参数。
      • parseFloat():主要用于将字符串转换为数值。
  10. String类型
    • 0个或多个16位Unicode字符序列
    • 可以用双引号(")、单引号(')或反引号(`)标示
    • 字符串的长度通过length属性过去,例:text.length
    • toString()方法:把一个值转换为字符串。对数值调用这个方法时,可以接受一个底数参数。null和undefined值没有这个方法。
    • String():当不确定一个值是不是null或undefined时用。
    • 用加号操作符给一个值加上一个空字符串""也可以将其转换为字符串。
    • 字符串差值:通过在${}中使用一个JavaScript表达式实现。嵌套的模板字符串无须转义,在插值表达式中可以调用函数和方法。模板也可以插入自己之前的值。
    • 模板字面量标签函数(没看懂!,到底什么是标签函数啊?)第67页
    • 原始字符串:String.raw标签函数,也可以通过标签函数的raw属性获得每个字符串的原始内容
  11. Symbol类型:(这里面蛮多不懂的地方,用到的时候再回来看)
    • 符号类型,确保对象属性使用唯一标识符。
    • 基本用法:
      • 使用Symbol()函数初始化。let sym = Symbol();
      • 调用Symbol()函数时,可以传入一个字符串参数作为对符号的描述,let othersym = Symbol(‘foo’);这个字符串参数可以用来调试代码,但是与符号定义或标识完全无关。
      • 符号没有字面量语法
      • Symbol()函数不能与new关键字一起作为构造函数使用
        let mySymbol = new Symbol(); // TypeError: Symbol is not a constructor
    • 使用全局符号注册表
      • 使用Symbol.for()方法:let fooGlobalSymbol = Symbol.for('foo');
      • 在全局注册表中定义的符号跟使用Symbol()定义的符号并不等同。
      • 全局注册表中的符号必须使用字符串来创建,因此作为参数传给Symbol.for()的任何值都会被转换为字符串。注册表中使用的键同时也会被用作符号描述。
        let emptyGlobalSymbol = Symbol.for();
        console.log(emptyGlobalSymbol); // Symbol(undefined)
      • 使用Symbol.keyFor()来查询全局注册表,返回该全局符号对应的字符串键。
        // 创建全局符号
        let s = Symbol.for('foo');
        console.log(Symbol.keyFor(s)); // foo
    • 使用符号作为属性(从这里开始往下的符号部分的内容没看懂,用到的时候再回来看)
    • 常用内置符号
  12. Object类型:
    • 对象实际就是一组数据和功能的集合。通过new操作符后跟对象类型的名称来创建(同Java)。例:let o = new Object();
    • 如果构造函数没有参数,可以省略括号,合法但不推荐。
    • 每个Object实例都有以下属性和方法:
      • constructor:用于创建当前对象的函数。
      • hasOwnProperty(propertyName):用于判断当前对象实例上是否存在给定的属性。
      • isPrototypeOf(Object):用于判断当前对象是否为另一个对象的原型。
      • propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用for-in语句枚举。
      • toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境。
      • toString():返回对象的字符串表示。
      • valueOf():返回对象对应的字符串、数值或布尔值表示。
    • Object是所有对象的基类,所以任何对象都有这些属性和方法。

5.操作符

  1. 一元操作符
    • 递增/递减操作符
      • 同C语言
      • 可以作用于任何值,整数,字符串,布尔值,浮点值甚至对象都可以。
    • 一元加和减
      • 同高中数学
      • 应用到非数值时会执行于使用Number()转型函数一样的类型转换。
      • 一元加(+)放到变量前头,对数值没有任何影响。
      • 一元减(-)放在变量前头,主要用于把数值变成负值。
      • 主要用于基本算数,也可用于数据类型转换。
  2. 位操作符
    • 在应用位操作时,在后台64位数值会转换为32位数值,然后执行位操作,最后再把结果从32位转换为64位存储起来。副作用是:特殊值NaN和Infinity在位操作中都会被当成0处理。
    • 应用到非数值,首先会使用Number()函数将该值转换为数值。
    • 按位非(~):返回数值的补数。
    • 按位与(&)
    • 按位或(|)
    • 按位异或(^)
    • 左移(<<):保留符号。
    • 有符号右移(>>):保留符号
    • 无符号右移(>>>)
  3. 布尔操作符
    • 逻辑非(!)
      • 返回值一定是布尔值。
      • 首先将操作符转换为布尔值,然后对其取反。
      • 同时使用两个叹号(!!),相当于调用了转型函数Boolean()。
      • 规则:
        如果操作数是对象,则返回false。
        如果操作数是空字符串,则返回true。
        如果操作数是非空字符串,则返回false。
        如果操作数是数值0,则返回true。
        如果操作数是非0 数值(包括Infinity),则返回false。
        如果操作数是null,则返回true。
        如果操作数是NaN,则返回true。
        如果操作数是undefined,则返回true。
    • 逻辑与(&&)
      • 如果有操作数不是布尔值,返回值不一定是布尔值。
      • 规则:
        如果第一个操作数是对象,则返回第二个操作数。
        如果第二个操作数是对象,则只有第一个操作数求值为true才会返回该对象。
        如果两个操作数都是对象,则返回第二个操作数。
        如果有一个操作数是null,则返回null。
        如果有一个操作数是NaN,则返回NaN。
        如果有一个操作数是undefined,则返回NaN。
    • 逻辑或(||)
      • 如果有操作数不是布尔值,返回值不一定是布尔值。
      • 规则
        如果第一个操作数是对象,则返回第一个操作数。
        如果第一个操作数求值为false,则返回第二个操作数。
        如果两个操作数都是对象,则返回第一个操作数。
        如果两个操作数都是null,则返回null。
        如果两个操作数都是NaN,则返回NaN。
        如果两个操作数都是undefined,则返回undefined。
  4. 乘性操作符:乘法、除法和取模。作用同Java,C语言。当操作数不是数值时,会在后台使用Number()转型函数转换为数值。
    • 乘法(*)
      • 操作符都是数值,执行常规乘法运算。如果不能表示乘积,则返回Infinity或-Infinity。
      • 如果有任一操作数是NaN,则返回NaN。
      • 如果是Infinity乘以0,则返回NaN。
      • 如果是Infinity乘以非0的有限数值,则根据第二个操作数的符号返回Infinity或-Infinity。
      • 如果是Infinity乘以Infinity,则返回Infinity。
      • 如果不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则。
    • 除法(/)
      • 操作符都是数值,执行常规除法运算。如果不能表示商,则返回Infinity或-Infinity。
      • 如果有任一操作数是NaN,则返回NaN。
      • 如果是Infinity除以Infinity,则返回NaN。
      • 如果是0除以0,则返回NaN。
      • 如果是非0的有限值除以0,则根据第一个操作数的符号返回Infinity或-Infinity。
      • 如果是Infinity除以任何值,则根据第二个操作数的符号返回Infinity或-Infinity。
      • 如果不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则。
    • 取模(%)
      • 如果操作数是数值,则执行常规除法运算,返回余数。
      • 如果被除数是无限值,除数是有限值,则返回NaN。
      • 如果被除数是有限值,除数是0,则返回NaN。
      • 如果是Infinity除以Infinity,则返回NaN。
      • 如果被除数是有限值,除数是无限值,则返回被除数。
      • 如果被除数是0,除数不是0,则返回0。
      • 如果不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则。
  5. 指数操作符:**
    • 等价于Math.pow()
    • 指数操作符也有自己的指数赋值操作符**=
  6. 加性操作符
    • 加法操作符(+)
    • 减法操作符(-)
  7. 关系操作符:都返回布尔值
    • 小于(<)
    • 大于(>)
    • 小于等于(<=)
    • 大于等于(>=)
  8. 相等操作符
    • 等于(==)和不等于(!=):先进行类型转换,再确定操作数是否相等。
    • 全等(===)和不全等(!==):比较相等时不转换操作数。
  9. 条件操作符:同Java中的三目运算符
    • variable = boolean_expression ? true_value : false_value;
  10. 赋值操作符
    • 简单赋值(=)
    • 复合赋值:使用乘性、加性或位操作符后跟等于号(=)表示
  11. 逗号操作符(,):可以用来在一条语句中执行多个操作

6.语句

  1. if语句:
    • if(condition) statement1 else statement2;
    • if(condition1) statement1 else if(condition2) statement2 else statement3;
  2. do-while语句
  3. while语句
  4. for语句:建议使用let声明迭代器变量
  5. for-in语句
    • 建议使用const声明变量
    • for(const property in expression) statement;
    • ECMAScript中对象的属性是无序的。因此for-in语句不能保证返回对象属性的顺序。
  6. for-of语句
    • 一种严格的迭代语句,用于遍历可迭代对象的元素
    • for(property of expression) statement;
    • 建议使用const声明迭代变量
    • 会按照可迭代对象的next()方法产生值的顺序迭代元素
  7. 标签语句
    • 用于给语句加标签,语法:label: statement
    • 标签可以通过break或continue语句引用。(不太明白)
  8. break和continue语句
    • break:立即退出循环,强制执行循环后的下一条语句。
    • continue:立即退出循环,再次从循环顶部开始执行。
    • 可以与标签语句一起使用,返回代码中特定的位置。(明白了)
  9. with语句
    • 用途是将作用域设置为特定的对象,语法:with(expression) statement;
    • 主要场景是针对一个对象反复操作
    • 严格模式不允许使用with语句,会抛出错误。
    • 影响性能难调试,不推荐使用!
  10. switch语句(同Java)

7.函数

  1. 使用function关键字声明,后跟一组参数,然后是函数体。
    function functionName(arg0,arg1,…,argN){
    statements
    }
  2. 使用函数名调用函数
  3. 不需要指定是否返回值,任何函数在任何时间都可以使用return语句来返回函数的值
  4. 不指定返回值的函数实际上会返回特殊值undefined