JavaScript红皮书学习笔记

1.什么是javaScript

  • JavaScript 历史回顾

  • JavaScript 是什么(实现)

JavaScript 是一门用来与网页交互的脚本语言,包含以下三个组成部分。

ECMAScript:由 ECMA-262 定义并提供核心功能。

​ 文档对象模型(DOM):提供与网页内容交互的方法和接口。

​ 浏览器对象模型(BOM):提供与浏览器交互的方法和接口。

  • JavaScriptECMAScript 的关系

ECMAScriptJavaScript的规格,JavaScript 实现了ECMAScript

  • JavaScript 的不同版本

2.HTML中的JavaScript

JavaScript 是通过<script>元素插入到 HTML 页面中的。这个元素可用于把JavaScript 代码嵌入到

HTML 页面中,跟其他标记混合在一起,也可用于引入保存在外部文件中的 JavaScript。本章的重点可以总结如下。

  • 要包含外部JavaScript 文件,必须将 src 属性设置为要包含文件的 URL。文件可以跟网页在同一台服务器上,也可以位于完全不同的域。

  • 所有<script>元素会依照它们在网页中出现的次序被解释。在不使用 deferasync 属性的情况下,包含在<script>元素中的代码必须严格按次序解释。

  • 对不推迟执行的脚本,浏览器必须解释完位于<script>元素中的代码,然后才能继续渲染页面的剩余部分。为此,通常应该把<script>元素放到页面末尾,介于主内容之后及</body>标签之前。

  • 可以使用defer 属性把脚本推迟到文档渲染完毕后再执行。推迟的脚本原则上按照它们被列出的次序执行。

  • 可以使用 async 属性表示脚本不需要等待其他脚本,同时也不阻塞文档渲染,即异步加载。异步脚本不能保证按照它们在页面中出现的次序执行。

  • 通过使用<noscript>元素,可以指定在浏览器不支持脚本时显示的内容。如果浏览器支持并启用脚本,则<noscript>元素中的任何内容都不会被渲染。

3.语言基础

3.1 变量

let 跟 var 最明显的区别是,let 声明的范围是块作用域,而 var 声明的范围是函数作用域。

  • var函数作用域:
if (true) { 
var name = 'Matt'; 
console.log(name); // Matt 
} 
console.log(name); // Matt
  • let块作用域:
 if (true) { 
   let age = 26; 
   console.log(age); // 26 
} 
console.log(age); // ReferenceError: age 没有定义

const 的行为与 let基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改 const 声明的变量会导致运行时错误。

3.2 数据类型

ECMAScript 有 6 种简单数据类型(也称为原始类型):UndefinedNullBooleanNumberStringSymbolSymbol(符号)是ECMAScript 6 新增的。

还有一种复杂数据类型叫 Object(对象)。Object 是一种无序名值对的集合。

  • typeof操作符

    因为 ECMAScript 的类型系统是松散的,所以需要一种手段来确定任意变量的数据类型。typeof操作符就是为此而生的。对一个值使用 typeof 操作符会返回下列字符串之一:
    "undefined"表示值未定义;
    "boolean"表示值为布尔值;
    "string"表示值为字符串;
    "number"表示值为数值;
    "object"表示值为对象(而不是函数)或 null;

    "function"表示值为函数;
    "symbol"表示值为符号。

    下面是使用 typeof 操作符的例子:

    let message = "some string"; 
    console.log(typeof message); // "string" 
    console.log(typeof(message)); // "string" 
    console.log(typeof 95); // "number" 
    

    在这个例子中,我们把一个变量(message)和一个数值字面量传给了 typeof 操作符。注意,因为 typeof 是一个操作符而不是函数,所以不需要参数(但可以使用参数)。
    注意typeof在某些情况下返回的结果可能会让人费解,但技术上讲还是正确的。比如,调用typeof null 返回的是"object"。这是因为特殊值 null 被认为是一个对空对象的引用。

    在其他地方看到前端判断数据类型的方法:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-99ATwSTN-1610439473146)(blob:file:///8740607f-d149-4616-8e5e-292f4bc32df4)]

  • Undefined类型

    ⚠️:即使未初始化的变量会被自动赋予 undefined 值,但我们仍然建议在声明变量的同时进行初始化。这样,当 typeof 返回"undefined"时,你就会知道那是因为给定的变量尚未声明,而不是声明了但未初始化。

  • Null类型

    Null 类型同样只有一个值,即特殊值 null。逻辑上讲,null 值表示一个空对象指针,这也是给
    typeof 传一个 null 会返回"object"的原因:

    let car = null; 
    console.log(typeof car); // "object"
    
  • Boolean类型

    Boolean()转型函数可以在任意类型的数据上调用,而且始终返回一个布尔值。什么值能转换为 true
    或 false 的规则取决于数据类型和实际的值。下表总结了不同类型与布尔值之间的转换规则。

    数据类型转换为 true 的值转换为 false 的值
    Booleantruefalse
    String非空字符串“”(空字符串)
    Number非零数值(包括无穷值)0、NaN(参见后面的相关内容)
    Object任意对象null
    UndefinedN/A(不存在)undefined
  • Number 类型

    1. 浮点值

      要定义浮点值,数值中必须包含小数点,而且小数点后面必须至少有一个数字。永远不要测试某个特定的浮点值

      if (a + b == 0.3) { // 别这么干!
       console.log("You got 0.3."); 
      }
      
    2. 值的范围

      由于内存的限制,ECMAScript 并不支持表示这个世界上的所有数值。ECMAScript 可以表示的最小数值保存在 Number.MIN_VALUE 中,这个值在多数浏览器中是 5e324;可以表示的最大数值保存在Number.MAX_VALUE 中,这个值在多数浏览器中是 1.797 693 134 862 315 7e+308。如果某个计算得到的数值结果超出了 JavaScript 可以表示的范围,那么这个数值会被自动转换为一个特殊的 Infinity(无穷)值。

    3. NaN

      NaN 不等于包括 NaN 在内的任何值。例如,下面的比较操作会返回 false:

      console.log(NaN == NaN); // false 
      
    4. 数值转换

      有 3 个函数可以将非数值转换为数值:Number()parseInt()parseFloat()

      Number()是转型函数,可用于任何数据类型。后两个函数主要用于将字符串转换为数值。

  • String 类型

    String(字符串)数据类型表示零或多个 16 位 Unicode 字符序列。字符串可以使用双引号(")、

    单引号(’)或反引号(`)标示,因此下面的代码都是合法的:

    let firstName = "John"; 
    let lastName = 'Jacob'; 
    let lastName = `Jingleheimerschmidt`
    
    • 转换为字符串
    1. toString()方法

      ⚠️:toString()方法可见于数值、布尔值、对象和字符串值。(没错,字符串值也有 toString()方法,该方法只是简单地返回自身的一个副本。)null 和 undefined 值没有 toString()方法。

      let age = 11; 
      let ageAsString = age.toString(); // 字符串"11" 
      let found = true; 
      let foundAsString = found.toString(); // 字符串"true" 
      
    2. String()转型函数

      ⚠️:如果你不确定一个值是不是 null 或 undefined,可以使用 String()转型函数,它始终会返回表示相应类型值的字符串。

      let value1 = 10; 
      let value2 = true; 
      let value3 = null; 
      let value4; 
      console.log(String(value1)); // "10" 
      console.log(String(value2)); // "true" 
      console.log(String(value3)); // "null" 
      console.log(String(value4)); // "undefined" 
      

    用加号操作符给一个值加上一个空字符串""也可以将其转换为字符串

    • 模板字面量

      ECMAScript 6 新增了使用模板字面量定义字符串的能力。与使用单引号或双引号不同,模板字面量保留换行字符,可以跨行定义字符串:

      let myMultiLineString = 'first line\nsecond line'; 
      let myMultiLineTemplateLiteral = `first line 
      second line`; 
      console.log(myMultiLineString); 
      // first line 
      // second line" 
      console.log(myMultiLineTemplateLiteral); 
      // first line
      // second line 
      console.log(myMultiLineString === myMultiLinetemplateLiteral); // true 
      
    • 字符串插值

      字符串插值通过在${}中使用一个 JavaScript 表达式实现:

      let value = 5; 
      let exponent = 'second'; 
      // 以前,字符串插值是这样实现的:
      let interpolatedString = 
       value + ' to the ' + exponent + ' power is ' + (value * value); 
      // 现在,可以用模板字面量这样实现:
      let interpolatedTemplateLiteral = 
       `${ value } to the ${ exponent } power is ${ value * value }`; 
      console.log(interpolatedString); // 5 to the second power is 25 
      console.log(interpolatedTemplateLiteral); // 5 to the second power is 25 
      
  • Symbol 类型

    Symbol(符号)是 ECMAScript 6 新增的数据类型。符号是原始值,且符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。

  • Object 类型

    ECMAScript 中的对象其实就是一组数据和功能的集合。对象通过 new 操作符后跟对象类型的名称

    来创建。开发者可以通过创建 Object 类型的实例来创建自己的对象,然后再给对象添加属性和方法:

    let o = new Object();

3.3操作符

  • 一元操作符

    只操作一个值的操作符叫一元操作符(unary operator)

    (1)递增/递减操作符(a++或–a)

    (2)一元加和减(a=+a或a=-a)

    (3)位操作符(按位非(~), 按位与(&),按位或(|), 按位异或(^),左移(<<),右移(>>),无符号右移(>>>))

  • 布尔操作符

    布尔操作符一共有 3 个:逻辑非(!)、逻辑与(&&)和逻辑或(||)。

  • 乘性操作符

​ ECMAScript 定义了 3 个乘性操作符:乘法(*)、除法(/)和取模(%)。

  • 指数操作符

    ECMAScript 7 新增了指数操作符,Math.pow()现在有了自己的操作符**,结果是一样的:

    console.log(Math.pow(3, 2); // 9 
    console.log(3 ** 2); // 9 
    

    不仅如此,指数操作符也有自己的指数赋值操作符**=,该操作符执行指数运算和结果的赋值操作:

    let squared = 3; 
    squared **= 2; 
    console.log(squared); // 9 
    
  • 加性操作符

    加性操作符,即加法(+)和减法(-)操作符,一般都是编程语言中最简单的操作符。加性操作符在后台会发生不同数据类型的转换。

  • 关系操作符

    关系操作符执行比较两个值的操作,包括小于(<)、大于(>)、小于等于(<=)和大于等于(>=),

    用法跟数学课上学的一样。

  • 相等操作符

    ECMAScript提供了两组操作符。第一组是等于和不等于,它们在比较之前执行转换。第二组是全等和不全等,它们在比较之前不执行转换。

    ​ (1)等于和不等于

    ​ ECMAScript 中的等于操作符用两个等于号(==)表示,如果操作数相等,则会返回 true。不等于操作符用叹号和等于号(!=)表示,如果两个操作数不相等,则会返回 true。这两个操作符都会先进行类型转换(通常称为强制类型转换)再确定操作数是否相等。

    ​ (2)全等和不全等

    ​ 全等和不全等操作符与相等和不相等操作符类似,只不过它们在比较相等时不转换操作数。全等操

    作符由 3 个等于号(===)表示,只有两个操作数在不转换的前提下相等才返回 true,比如:

    let result1 = ("55" == 55); // true,转换后相等
    let result2 = ("55" === 55); // false,不相等,因为数据类型不同
    
  • 条件操作符

    条件操作符是 ECMAScript 中用途最为广泛的操作符之一,语法跟 Java 中一样:

    variable = boolean_expression ? true_value : false_value; 
    

    上面的代码执行了条件赋值操作,即根据条件表达式 boolean_expression 的值决定将哪个值赋

    给变量 variable 。如果 boolean_expression 是 true ,则赋值 true_value ;如果

    boolean_expression 是 false,则赋值 false_value。

  • 赋值操作符

    简单赋值用等于号(=)表示,将右手边的值赋给左手边的变量,如下所示:

    let num = 10; 
    

    复合赋值使用乘性、加性或位操作符后跟等于号(=)表示。这些赋值操作符是类似如下常见赋值

    操作的简写形式:

    let num = 10; 
    num += 10; 
    
  • 逗号操作符

    逗号操作符可以用来在一条语句中执行多个操作,如下所示:

    let num1 = 1, num2 = 2, num3 = 3; 
    

    在一条语句中同时声明多个变量是逗号操作符最常用的场景。不过,也可以使用逗号操作符来辅助

    赋值。在赋值时使用逗号操作符分隔值,最终会返回表达式中最后一个值:

    let num = (5, 1, 4, 8, 0); // num 的值为 0 
    

    在这个例子中,num 将被赋值为 0,因为 0 是表达式中最后一项。逗号操作符的这种使用场景并不

    多见,但这种行为的确存在。

3.4语句

  • if 语句

    if 语句是使用最频繁的语句之一,语法如下:

    if (condition) statement1 else statement2 
    
  • do-while 语句

    do-while 语句是一种后测试循环语句,即循环体中的代码执行后才会对退出条件进行求值。换句话说,循环体内的代码至少执行一次。do-while 的语法如下:

    do { 
     	statement 
    } while (expression); 
    
  • while 语句

    while 语句是一种先测试循环语句,即先检测退出条件,再执行循环体内的代码。因此,while 循

    环体内的代码有可能不会执行。下面是 while 循环的语法:

    while(expression) statement

    这是一个例子:

    let i = 0; 
    	while (i < 10) { 
    	i += 2; 
    }
    
  • for 语句

    for 语句也是先测试语句,只不过增加了进入循环之前的初始化代码,以及循环执行后要执行的表达式,语法如下:

    for (initialization; expression; post-loop-expression) statement

    下面是一个用例:

    let count = 10; 
    for (let i = 0; i < count; i++) { 
     console.log(i); 
    } 
    
  • for-in 语句

    for-in 语句是一种严格的迭代语句,用于枚举对象中的非符号键属性,语法如下:

    for (property in expression) statement

    下面是一个例子:

    for (const propName in window) { 
     	document.write(propName); 
    } 
    
  • for-of 语句

    for-of 语句是一种严格的迭代语句,用于遍历可迭代对象的元素,语法如下:

    for (property of expression) statement

    下面是示例:

    for (const el of [2,4,6,8]) { 
     document.write(el); 
    }
    
  • 标签语句

    标签语句用于给语句加标签,语法如下:

    label: statement

    下面是一个例子:

    start: for (let i = 0; i < count; i++) { 
     	console.log(i); 
    } 
    

    在这个例子中,start 是一个标签,可以在后面通过 break 或 continue 语句引用。标签语句的

    典型应用场景是嵌套循环。

  • breakcontinue 语句

    break 和 continue 语句为执行循环代码提供了更严格的控制手段。其中,break 语句用于立即退

    出循环,强制执行循环后的下一条语句。而 continue 语句也用于立即退出循环,但会再次从循环顶部

    开始执行。

  • with 语句

    with 语句的用途是将代码作用域设置为特定的对象,其语法是:

    with (expression) statement;

    ⚠️:由于 with 语句影响性能且难于调试其中的代码,通常不推荐在产品代码中使用 with

    语句。

  • switch 语句

    switch 语句是与 if 语句紧密相关的一种流控制语句,从其他语言借鉴而来。

3.5 函数

​ 函数对任何语言来说都是核心组件,因为它们可以封装语句,然后在任何地方、任何时间执行。

ECMAScript 中的函数使用 function 关键字声明,后跟一组参数,然后是函数体。

以下是函数的基本语法:

function functionName(arg0, arg1,...,argN) { 
 	statements 
} 

下面是一个例子:

function sayHi(name, message) { 
 	console.log("Hello " + name + ", " + message); 
} 

4 变量、作用域与内存

​ JavaScript 变量是松散类型的,而且变量不过就是特定时间点一个特定值的名称而已。

4.1 原始值与引用值

​ ECMAScript 变量可以包含两种不同类型的数据:原始值和引用值。原始值(primitive value)就是

最简单的数据,引用值(reference value)则是由多个值构成的对象。

​ 保存引用值的变量是按引用(by reference)访问的

  • 动态属性

    原始值和引用值的定义方式很类似,都是创建一个变量,然后给它赋一个值。不过,在变量保存了

    这个值之后,可以对这个值做什么,则大有不同。对于引用值而言,可以随时添加、修改和删除其属性

    和方法。

    let person = new Object(); 
    person.name = "Nicholas"; 
    console.log(person.name); // "Nicholas" 
    

    原始值不能有属性,尽管尝试给原始值添加属性不会报错。比如:

    let name = "Nicholas"; 
    name.age = 27; 
    console.log(name.age); // undefined 
    
  • 复制值

    ​ 除了存储方式不同,原始值和引用值在通过变量复制时也有所不同。在通过变量把一个原始值赋值

    到另一个变量时,原始值会被复制到新变量的位置。
    在这里插入图片描述
    ​ 在把引用值从一个变量赋给另一个变量时,存储在变量中的值也会被复制到新变量所在的位置。区

    别在于,这里复制的值实际上是一个指针,它指向存储在堆内存中的对象。操作完成后,两个变量实际

    上指向同一个对象,因此一个对象上面的变化会在另一个对象上反映出来
    在这里插入图片描述

  • 传递参数

    ​ ECMAScript 中所有函数的参数都是按值传递的。这意味着函数外的值会被复制到函数内部的参数

    中,就像从一个变量复制到另一个变量一样。如果是原始值,那么就跟原始值变量的复制一样,如果是

    引用值,那么就跟引用值变量的复制一样。对很多开发者来说,这一块可能会不好理解,毕竟变量有按

    值和按引用访问,而传参则只有按值传递

    ​ 很多开发者错误地认为,当在局部作用域中修改对象而变化反映到全局时,就意味着参数是按引用传递的。

  • 确定类型

    ​ typeof 操作符最适合用来判断一个变量是否为原始类型。更确切地说,它是判断一个变量是否为字符串、数值、布尔值或 undefined 的最好方式。如果值是对象或 null,那么 typeof返回"object"。

    ​ typeof 虽然对原始值很有用,但它对引用值的用处不大。我们通常不关心一个值是不是对象,而是想知道它是什么类型的对象。为了解决这个问题,ECMAScript 提供了 instanceof 操作符,语法如下:

    result = variable instanceof constructor

    例子:

    console.log(person instanceof Object); // 变量 person 是 Object 吗?
    console.log(colors instanceof Array); // 变量 colors 是 Array 吗?
    console.log(pattern instanceof RegExp); // 变量 pattern 是 RegExp 吗?
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值