美文网首页
JavaScript 中目前比较少见的表达式

JavaScript 中目前比较少见的表达式

作者: ByePast | 来源:发表于2021-06-07 23:11 被阅读0次

    ??空值合并运算符es2020

    ??是一个逻辑操作符,当左侧的操作数为 null或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。

    与逻辑或操作符||不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。
    比如为假值(例如,''0)时。见下面的例子:

    const foo = null ?? 'default string'
    console.log(foo) // "default string"
    
    const baz = 0 ?? 42
    console.log(baz) // 0
    
    const bar = false ?? true
    console.log(bar) // false
    

    注意??不能与 &&|| 操作符共用

    null || undefined ?? "foo" // 抛出 SyntaxError
    true || undefined ?? "foo" // 抛出 SyntaxError
    

    但是,如果使用括号来显式表明运算优先级,是没有问题的:

    (null || undefined ) ?? "foo" // 返回 "foo"
    

    ?.可选链操作符es2020

    可选链操作符?.允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。
    ?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空值要么是 null要么是 undefined的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined

    const adventurer = {
      name: 'Alice',
      cat: {
        name: 'Dinah'
      }
    }
    
    const dogName = adventurer.dog?.name
    console.log(dogName) // undefined
    
    console.log(adventurer.someNonExistentMethod?.()) // undefined
    
    console.log(adventurer.list?.forEach(() => {})) // undefined
    

    对比一下代码

    const obj = {}
    let nestedProp = obj.first?.second
    

    这等价于以下表达式,但实际上没有创建临时变量:

    const obj = {}
    let temp = obj.first
    let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second)
    

    可选链与函数调用
    当尝试调用一个可能不存在的方法时也可以使用可选链。

    • 函数调用时如果被调用的方法不存在,使用可选链可以使表达式自动返回undefined而不是抛出一个TypeError
    const someInterface = {}
    let result = someInterface.customMethod?.()
    

    可选链和表达式
    当使用方括号与属性名的形式来访问属性时,你也可以使用可选链操作符:

    let list = null
    console.log(list?.[1]) // undefined
    

    注意

    • 如果存在一个属性名且不是函数, 使用 ?. 仍然会产生一个TypeError异常
    const someInterface = {
       customMethod: 'Not Method'
    }
    
    let result = someInterface.customMethod?.();
    // Uncaught TypeError: someInterface.customMethod is not a function
    
    • 如果 someInterface 自身是 null 或者 undefined, 仍然会产生一个TypeError异常,如果你希望允许 someInterface 也为 null 或者 undefined,那么你需要像这样写:
    let someInterface = null
    someInterface?.customMethod?.() // undefined
    

    逗号运算符间接函数调用

    先介绍一下逗号运算符
    逗号运算符

    对它的每个操作数求值(从左到右),并返回最后一个操作数的值。

    let x = 1
    x = (x++, x)
    console.log(x) // 2
    
    x = (2, 3)
    console.log(x) // 3
    

    (0, alert)('ByePast')逗号运算符衍生出来的间接函数调用

    使用间接函数调用可以把该作用域内倍的this指向全局对象中的this

    在调用函数的上下文中,对操作数的评估只会得到一个值,而不是引用,这会导致this被调用函数内部的值指向全局对象(或者它将undefined处于新的 ECMAScript 5 严格模式)例如:

    var foo = 'global.foo'
    
    var obj = {
      foo: 'obj.foo',
      method: function () {
        return this.foo
      }
    };
    
    obj.method() // 'obj.foo'
    (1, obj.method)() // 'global.foo'
    

    如您所见,第一次调用,即直接调用,this内部的值method将正确引用obj(返回'obj.foo'),第二次调用,逗号运算符所做的评估将使this值指向全局对象(产生'global.foo')。

    这种模式很流行,要间接调用eval,这在 ES5 严格模式下很有用,例如,获取对全局对象的引用(假设您在非浏览器环境中,window不是可用的)

    (function () {
      'use strict';
      var global = (function () { return this || (1, eval)('this') })();
    })();
    

    在上面的代码中,内部匿名函数将在严格模式代码单元内执行,这将导致this值为undefined

    ||运营商现在就第二个操作数的eval调用,这是一个间接调用,它将评估对全球词法和环境变量的代码。

    但就我个人而言,在这种情况下,在严格模式下,我更喜欢使用Function构造函数来获取全局对象:

    (function () {
      'use strict'
      var global = Function('return this')()
    })()
    

    使用Function构造函数创建的函数只有在以 use strict 指令开头时才是严格的,它们不像函数声明或函数表达式那样“继承”当前上下文的严格性

    相关文章

      网友评论

          本文标题:JavaScript 中目前比较少见的表达式

          本文链接:https://www.haomeiwen.com/subject/bgsreltx.html