《深入理解JavaScript》笔记

参考:深入理解JavaScript



最下面有几点疑问,路过的朋友帮忙解答下

七、JavaScript 的语法

  1. 多行注释 ,被/* */包裹的任意区域,它不能嵌套使用
function (a /* int */, b /* str */) {}
  1. 表达式 将会产生一个值,它可以写在任何需要值的地方。
  2. 语句 表示了一种行为,如循环和if语句,一个程序基本上就是语句的序列。

凡是在JavaScript期望语句的地方都可以写表达式,这样的语句叫做表达式语句。反之则不然:不能在需要表达式的地方使用语句。

  1. 有两种像语句的表达式类型,它们的语法类型是 二义 的。
  • 对象字面量(表达式)看上去像块(语句):
{
  foo: bar(3, 5)
}
  • 具名函数表达式看上去像是函数声明(语句):
function foo() {}

为了避免二义性,在解析过程中,JavaScirpt不能使用对象字面和函数表达式作为语句,即表达式语句不能以 花括号function关键字 内容开头。

  1. eval 在语句的上下文中解析它的参数。如果希望 eval 返回一个对象,需要用小括号将对象字面两括起来。
eval('{ x: 123 }')
// output: 123
eval('({ x: 123 })')
//output: { x: 123 }
  1. 在调用 数字变量 的方法时,区分是浮点数的小数点还是调用方法的点运算符是非常重要的。因此不可以写类似 1.toString() 这样的代码,必须使用以下一种方式:
1..toString()
1 .toString()  // space before dot
(1).toString()
1.0.toString()
  1. 可以在 JavaScript 文件或者 <script> 标签的第一行加入以下代码来启用严格模式:
'use strict'
 ...

也可以为每个函数启用严格模式:

function foo() {
  'use strict'
   ...
}

启用严格模式需要注意的问题:

  • 启用严格模式可能会破坏 现有的 代码
  • 变量必须被声明
  • 函数必须在作用域的顶部声明
  • arguments对象拥有更少的属性
  • 无方法的函数中 this 的值为 undefined
  • 设置或者删除不可改变的属性(对属性的非法操作)会抛出异常
  • 严格模式中, eval 更加简洁
  • with 语句不能再被调用
  • 没有八进制数字

八、值

  1. 静态与动态
    在编程语言的语义和类型体系环境中,静态一般是指 “编译时” 或 “非运行时”,动态指的是 “运行时”。
  2. 静态类型动态类型
    在静态类型语言中,变量、参数和对象成员(JavaScript 称他们为属性)都有编译器编译时能识别的类型。编译器可以通过这些信息执行类型检查和优化编译的代码。
    即使在动态类型语言中,变量依然有一个动态的类型,是指在执行的某一时刻变量值的类型。
    JavaScript 是动态类型语言;变量的类型在编译的时候是不确定的。
  3. 静态类型检查语言 会在编译期间进行检查,动态类型检查语言 会在执行期间进行检查。一种语言可以同时做静态类型检查和动态类型检查。
    • 原始值 包括布尔值、数字、字符串、nullundefined
    • 其它值都是 对象,包括 简单对象数组正则表达式

两者之间最主要的区别是类别内是如何互相比较的。每一个对象有唯一的标识符并且只严格和自身相等:

let obj1 = {}
let obj2 = {}
obj1 === obj2  // false
let obj3 = obj1
obj1 === obj3  // true

相反,所有原始值,只要编码值相同,则被认为相等

  1. 原始值具有以下特点:
    a. 按值进行比较
    b. 不可改变:其属性不能被改变、添加或移除

    let str = 'string'
    str.length = 3
    str.length //  output: 6
    
    str.add = 'add'
    str.add //  output: undefined
    

    c. 固定类型的组合:你不能够自定义原始值

  2. 对象的特点:
    a. 按引用进行比较

    // two different empty objects
    { } === { }  // output: false
    

    b. 默认可变

    对象属性可以很自由地被改变、添加和移除

    c. 用户可扩展

    构造函数可以被看做是自定义类型的补充

  3. JavaScript 有两个“空值”用来表示信息缺失,undefinednull

    • undefined 表示“没有值”,不存在的元数据。
    • null 表示“空值”,意思是“没有对象”。在用到对象的时候它表示空值。

    例如,访问一个 JSON 节点时返回值的意义如下

    • undefined 表示删除一个对象属性或者数组元素
    • null 表示将属性或者元素设置为空

    undefinednull 是仅有的在访问任何属性抛出异常时都会得到的值

    function returnFoo(x) { return x.foo }
    returnFoo(true)  //  output: undefined
    returnFoo(0) //  output: undefined
    returnFoo(null)
    // output:  Cannot read property 'foo' of null
    returnFoo(undefined)
    // output:  Cannot read property 'foo' of undefined
    
  4. undefined 出现的场景

    • 未初始化的变量
    • 缺失的参数
    • 访问一个不存在的属性
    • 函数中没有显式地返回任何值
  5. null 出现场景

    • null 是原型链最顶端的元素
    Ojbect.getPrototypeOf(Object.prototype)
    //  output:  null
    
  • 当字符串中没有匹配到正则表达式的结果时,RegExp.prototype.exec() 会返回null
    /x/.exec('aaa')
    //  output:  null
    
  1. undefinednull 的历史
    JavaScript 采用了 Java 中将变量分为原始值和对象的处理方式。同时也使用 Java 中表示“非对象”的值 null。遵循 C语言 的先例,null 在强制转换为数字时会变为0( Java 不会这样)

     Number(null)
    //  output:  0
    5 + null
    // output:  5
    

值得注意的是,JavaScript 的第一版没有异常处理。因此,在遇到未初始化的变量和缺失的参数等异常情况时需要通过一个值来表示。null 是一个很好的选择,但是 Brendan Eich 想要在这个时候避免两种情况。

  • 这个值不应该具有指向性,因为它表达的不仅仅是一个对象

  • 这个值的强制转换不应该为 0,因为这会使错误难以发现
    因此,Eichundefined 作为另外一个空值加进了 JavaScript。它会强制转换为 NaN

     Number(undefined)
     //output:  NaN
     5 + undefined
     //output:  NaN
    
  1. 布尔值、数字和字符串这三种原始值都有相应的构造函数:BooleanNumberString。这些构造函数有两种用法:

    • 作为构造函数,它们 创建的对象 / 实例(称为 包装对象 )和它们包装的原始值有很大的不同

       typeof new  String('str')
       //output:  'object'
       new String('str') === 'str'
       //output:  false
      
    • 作为函数,它们会将值转换为相应的原始值。这是推荐的转换方法

       String(123)
       //output:  '123' 
       String(new String('str'))  === 'str'
      // true
      

      包装实例是对象,而在 JavaScript 中没有比较对象的方法,即使是通过宽松相等 ==。

       var a = new String('str')
       var b = new String('str')
       a == b
      //  false
      
  2. 原始值没有私有方法,但是它们会从各自的包装器中 借调 方法

     'str'.charAt === String.prototype.charAt
     //output:  true
    'str'.trim ==== String.prototype.trim
    //output:  true                
    

    宽松模式和严格模式会以不同的方式处理“借调”过程。
    在宽松模式中,原始值会在运行过程中转换为包装器:

    String.prototype.method = function () {
       console.log(this)  // String {"str"}
       console.log(typeof this)  //  object
       console.log(this instanceof String)  //  true
    }
    'str'.method()  //  call the above method
    

    在严格模式中,对包装器原型方法的调用是透明的:

    String.prototype.method = function () {
      "use strict"
      console.log(this)  //  str
      console.log(typeof this)  //  string
      console.log(this instanceof String)  //  false
    }
    'str'.method()  // call the above method
    
  3. 转换为布尔值:Boolean()

    Boolean(NaN)
    //  false
    
  4. 转换为数字:Number()

    Number(undefined)
    //  NaN
    Number(null)
    //  0
    Number(false)
    //  0
    Number(true)
    //  1
    Number('123')
    // 123
    
  5. 转换为字符串:String()

    String(undefined)
    //  'undefined'
    String(null)
    //  'null'
    String(false)
    //  'false'
    
  6. Object() 把对象会转换为它们自身,undefinednull 会转换成空对象,而原始值会转换为包装后的原始值。

    var obj = { foo: 123 }
    Object(obj) === obj
    //  true
    Object(null)
    //  {}
    Object(undefined)
    //  {}
    Object('abc') instanceof String
    //  true
    Object(NaN) instanceof Number
    //  true
    

九、运算符

  1. 连等赋值 x = y = 0,可以看这个案例

  2. 复合赋值运算符,var1 op= var2var1 = var1 op var2,这两个表达式是等价的,其中 op 是一种二元运算符。以下列出所有的复合赋值运算符:

    • 算数运算符:+=-+×=/=%=
    • 位运算符:<<=>>=>>>=&=^=|=
    • 字符拼接:+=
  3. 宽松相等 ( == ) 和不等 ( != ) 会先尝试将两个不同类型的值进行转换,再使用严格相等进行比较。
    如果运算数是如下类型:
    (1) undefinednull,则它们被认为是宽松相等的

    undefined == null  //  true
    

    (2) 一个字符串和一个数字,则将字符串转换为数字,使用严格相等比较两个运算数。
    (3) 一个布尔值和一个非布尔值,则将布尔值转换为一个数字,然后(再次)进行宽松比较。

    ' '  == false  //  true
    '0' == false  //  true
    '1' == true  //  true
    '2' == true  //  false
    '2' == false  //  false
    

    (4) 一个对象和一个数字或者字符串,则尝试转换此对象为一个原始值(ToPrimitive() —— 将值转换为原始值),然后(再次)进行宽松比较。
    (5) 其它情况宽松比较的结果为 false

    特殊数字NaN和本身不相等
    NaN === NaN
    // false
    严格不等x !== y等价于!(x === y)



疑问1:第九章运算符下第三点,"宽松相等 ( == ) 和不等 ( != ) 会先尝试将两个不同类型的值进行转换,再使用严格相等进行比较。",譬如:

 '1' == 1  //  true

但是比较:0 == null,我们知道Number(null)等于0,结果为什么却是false,如果把null强制转换为数字类型,0 == Number(null),结果为true

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,135评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,317评论 3 397
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,596评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,481评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,492评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,153评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,737评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,657评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,193评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,276评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,420评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,093评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,783评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,262评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,787评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,427评论 2 359

推荐阅读更多精彩内容