美文网首页
11+ JavaScript Features You’ve P

11+ JavaScript Features You’ve P

作者: QLing09 | 来源:发表于2020-08-21 22:56 被阅读0次

    最近在备考雅思,空下来就翻译一下技术文章,增加阅读能力。这篇文章来自medium,作者:Chidume Nnamdi,文章原文地址

    ⚠ 重要 ⚠

    这篇文章描述的部分功能已经被弃用了,有些功能被EcmaScript禁用了。这些功能仍然在许多图书馆中很常见,还是值得我们学习了解的。

    仅供参考。

    标记模板字符串

    taggingThis`Hey!!, I'm  ${name} !!`
    

    如果已经用过React样式组件化,那么就已经用过标记模板字符串。
    带有模板标记的字符串可以更好的控制字符串解析。允许我们使用函数来解析模板字符串。

    taggingThis`Hey!!, I'm  ${name} !!`
    

    taggingThis是一个功能。标记函数的第一个参数包含字符串值的数组,其余参数与表达式相关。

    function taggingThis(strings, ...vals) {
        //...
    }
    taggingThis`Hey!!, I'm  ${name} !!`
    

    strings参数将保持在[ "Hey!!, I'm ", ' !!' ],其余的参数传递到数组中,vals[ 'Nnamdi' ]

    这个taggingThis函数里面,可以操作入参和返回不同内容。

    function taggingThis(strings, ...vals) {
        return strings[0] + vals[0] + strings[1]
    }
    const name = "Nnamdi"
    taggingThis `Hey!!, I'm  ${name} !!` // Hey!!, I'm  Nnamdi !!
    

    样式组件标记字符串

    逗号运算符

    逗号运算符分割表达式和返回链中的最后一个表达式。

    let expr = (99, 88, 77)
    expr // 77
    

    有三个表达式99,88和77。所有的表达式都被求值和最后一个被赋值给expr

    下面这个for循环:

    for(let i = 0, ii = 1; i< 10; i++, ii--) { ... }
    

    当想写一个简短的lambda函数,逗号运算符会派上用场。

    const lb = (a, b, arr) => (arr.push(a*b), a*b)
    

    这里面有两个语句,第一个语句将乘法结构推入数组arr,第二个语句是a*b。第二个结果就是返回给回调者的内容。

    三元运算符逗号也是很有用,和短lambda函数语法相同,仅接受表达式,不是接受语句。

    with语句

    ⚠注意⚠
    通常不建议使用with语句,已经被废弃了。在严格模式下被禁止了。使用with会增加js语言性能和安全上的问题。

    with是JS中的关键字。用于扩展语句的作用于链。

    下面这样使用:

    with(expression)
        statement
    // OR
    with(expression) {
        statement
        statement
        ...
    }
    

    计算表达式并围绕表达式创建作用域。with语句的表达式和父作用域在大括号里面。

    const a = 45
    let b = 8
    var f = 909
    with(f) {
        log(f, b, a) // 909 8 45
    }
    

    f是包裹在作用域链中。fwith语句块外面声明的外部变量在with语句块里面可见。

    注意,letconstwith语句里面声明的变量只能在语句里面可以用,外部不可以调用。

    with(f) {
        log(f, b, a) // 909 8 45
        let withinF = 20
    }
    log(withinF) // undefined
    

    调用withinF方法,将会抛出ReferenceError错误,因为变量withinF只存在with语句块里面。

    尽量避免使用with

    更多细节

    in

    in也是一个关键字,检查对象里面存在的属性。在for..in循环中就使用,但没有意识到in就是关键字。

    如果对象里面存在这个属性in将返回true,否则将返回false。

    const o = {
        prop: 90
    }
    log("prop" in o) // true
    

    上面in是独立使用的,并没有for...in循环。

    将检查prop是否可作为o对象里面的属性使用。返回ture,因为已经在o里面定义了prop

    如果检查未定义的属性:

    const o = {
        prop: 90
    }
    log("prop1" in o) // false
    

    打印出false。因为prop1在o这个对象里面没有定义。

    已经用过这些功能了吗?

    更多了解

    数组构造函数

    知道吗?可以不用传统的方式定义数组。

    const arr = [90,88,77]
    

    用数组构造函数

    const arr = new Array(90, 88, 77)
    

    传递给构造函数的参数排序将构成其索引的基础。

    90第一个参数索引是0,88第二参数索引是1,77最后一个参数索引是2.

    arr[0] // 90
    arr[1] // 88
    arr[2] // 77
    

    new Array(...)和使用数组是一样的。

    那么

    const arr = new Array(90, 88, 77)
    

    同下面是一样的

    const arr = [90, 88, 77]
    

    有人认为使用数组构造函数功能有些缺点或不一致:
    Why never use new Array in Javascript

    使用new的方式创建一个数组,适用于构造函数new Array()的参数大于或等于2的情况。

    这样做

    const arr = new Array(90, 88, 77)
    

    将创建数组[90, 88, 77].因为new Array(..)的参数为3,即>=2.

    new Array(..)传递一个参数,将导致JS引擎为传递参数大小的数组分配空间。

    const arr = new Array(6)
    

    将创建一个包含6项或元素的数组,长度为6。

    const arr = new Array(6)
    arr // [ <6 empty items> ]
    arr.length // 6
    

    const arr = new Array(6)同下:

    const arr = [, , , , , ]
    arr // [ <6 empty items> ]
    arr.length // 6
    

    如果说这是JS不一致或偏激的功能,我不会同意。这在EcmaScript规范中。


    这并不矛盾。规范中都有描述。在给出结论之前,我们首先应该始终先阅读语言的规范。

    Function构造函数

    可以用Function构造函数定一个一个Function。

    接下来讲清楚。在JS里我们定义一个函数像这样:

    const mul = (a, b) => a * b
    
    // OR
    
    function mul(a, b) {
        return a * b
    }
    
    // OR
    
    const mul = function(a, b) {
        return a * b
    }
    
    

    我们仍然可以像下面这样做:

    const mul = new Function("a", "b", "return a * b")
    

    传递给Function的参数形成函数的参数和主体。mul变量变成函数的名称。

    最后的参数将变成函数的主体,那么最后参数的前面将会变成函数的参数。

    mul中,参数ab是函数将接收的参数,参数return a * b是函数的主体。a和b相乘然后返回结果。

    调用函数在括号里面传参数mul(…)

    const mul = new Function("a", "b", "return a * b")
    
    log(mul(7, 8)) // 56
    

    根据MDN 文档:

    直接调用构造函数可以动态创建函数,但存在安全和评估方面类似的(但重要性不高)问题。但是,与eval不同,Function构造函数创建的函数仅在全局范围内执行。

    更多内容

    解构数组

    我们可以使用元素的索引来分解数组的元素。

    const arr = [99, 88, 77]
    

    元素99, 88, 77有索引0, 1, 2.从数组arr中获取元素99,我们将其作为属性传递给arr,

    arr[1]

    就像处理对象一样:

    let o = {
        prop: 99
    }
    o[prop] // 99
    

    可以像这样从o对象里面解构属性:

    const {prop} = o
    prop // 99
    

    同样可以这样操作数组:

    const arr = [99, 88, 77]
    
    const { 1: secA } = arr
    secA // 88
    
    const { 0: firstA, 1: secA, 2: thirdA  } = arr
    
    firstA // 99
    secA // 88
    thirdA // 77
    

    我们使用索引号提取元素。索引是定义数组中元素位置的属性。

    const arr = [99, 88, 77]
    

    和下面的相同:

    const arr = {
        0: 99,
        1: 88,
        2: 77,
        length: 3
    }
    

    数组也是对象,这就是为什么用对象的方式去解构数组效果一样,但还有一种特殊的语法解构数组:

    const [first, second, third] = arr;

    尽可能的避免知道数组中的特定位置信息(开始索引,结束索引)。

    Reducing Array contents using the length property

    可以操作length属性减少数组。

    数组中的length属性是指数组中的长度。

    const arr = [99, 88, 77]
    arr.length // 3
    

    减少length属性,JS引擎将元素减少为与length属性。

    const arr = [99, 88, 77]
    arr.length // 3
    arr.length = 1
    arr // [ 99 ]
    

    arr的length属性更改为1,因此从右侧减少了元素,使其长度等于设置的length属性的值。
    如果增加length属性,JS引擎将会增加元素(未定义),使数组元素长度符合length属性值。

    const arr = [99, 88, 77]
    arr.length // 3
    arr.length = 1
    arr // [ 99 ]
    
    arr.length = 5
    arr // [ 90, <4 empty items> ]
    

    数组中只有一个,如果增加长度到5,那么增加了4个空到数组里面,使数组长度达到5.

    Arguments

    arguments获取函数传递的参数。这样做的好处,可以使用arguments对象传参数给函数,无需确切的定义函数参数。

    function myFunc() {
        arguments[0] // 34
        arguments[1] // 89
    }
    
    myFunc(34,89)
    

    arguments对象是数组索引。也就是说,属性是数字,所以就可以通过键值索引。
    arguments对象是通过Arguments类实例化的,该类具有一些很酷的属性。

    arguments.callee.name这是指当前被调用的函数名称。

    function myFunc() {
        log(arguments.callee.name) // myFunc
    }
    
    myFunc(34, 89)
    

    arguments.callee.name引用调用当前执行函数的函数的名称。

    function myFunc() {
        log(arguments.callee.name) // myFunc
        log(arguments.callee.caller.name) // myFuncCaller
    }
    
    (function myFuncCallee() {
        myFuncCaller(34, 89)
    })()
    

    可变参数在函数中是特别有用的。

    更多内容

    Skip the brackets

    实例化对象,可以忽略括号().

    例如:

    class D {
        logger() {
            log("D")
        }
    }
    
    // Normally, we do this:
    (new D()).logger() // D
    
    // Also, we can skip the ():
    (new D).logger() // D
    // and it still works
    

    括号是可选的,即使在内置类中也是如此。

    (new Date).getDay()
    (new Date).getMonth()
    (new Date).getYear()
    

    void operator

    void是JS中的关键字,是一个陈述语句,然后返回undefined.

    例如:

    class D {
       logger() {
            return 89
        }
    }
    
    const d = new D
    
    log(void d.logger()) // undefined
    

    logger方法应该返回89,但void关键字将无效并返回undefined.

    之前未定义的值可以被分配给另一个值,会伪造定义。void操作符可以确保真正的undefined。用于最小化目的。

    更多内容

    Function property

    可以在函数中设置属性:

    function func() {
        func.prop1 = "prop1"
    }
    func.prop2 = "prop2"
    

    函数也是对象,所以上面的写法是有效的。当使用对象时,Function属性将是Function所有实例的静态属性。

    const j1 = new func()
    const j2 = new func()
    j1.prop1 // prop1
    j2.prop1 // prop1
    j1.prop1 = "prop1 changed"
    j2.prop1 // prop1 changed
    

    当用作是函数时,将是全局属性。

    function func() {
        func.prop1 === undefined ? func.prop1 = "yes" : null
        if(func.prop1 === "yes")
            log("Prop with Yes")
        if (func.prop1 == "no")
            log("Prop with No")
    }
    func() // Prop with Yes
    func.prop1 = "no"
    func() // Prop with No
    

    Inheritance via proto

    _proto_是从JavaScript中的对象继承属性的方法。
    Object.prototype__proto__ 属性是一个访问器属性(一个getter函数和一个setter函数), 暴露了通过它访问的对象的内部[[Prototype]] (一个对象或 [null])。

    看一个例子:

    // proto.js
    const log = console.log
    const obj = {
        method: function() {
            log("method in obj")
        }
    }
    const obj2 = {}
    obj2.__proto__ = obj
    obj2.method()
    

    两个对象字面量:obj和obj2都有一个merhod属性方法。obj2是一个空对象字面量,没有属性。

    接下来,访问obj2的__proto__,并将obj赋值给它。通过Object.prototype将obj所有的可访问的属性赋值给obj2.这就是为什么在没有定义的情况下可以调用obj2上面的method,而且没有报错。

    $ node proto
    method in obj
    

    obj2继承了obj的属性,那么在它的属性里面,method方法将可用。

    proto用于对象,例如:object literal, Object, Array, Function, Date, RegEx, Number, Boolean, String.

    Unary + Operator

    一元+操作符将其操作数转换为Number类型。

    +"23" // 23
    +{} // NaN
    +null // 0
    +undefined // NaN
    +{ valueOf: () => 67 } // 67
    +"nnamdi45" // NaN
    

    当我们想快速将变量转换为Number类型时,这非常方便。

    Unary — Operator

    一元运算符将其操作数转换为Number类型,然后取反。
    该运算符将一元+运算符的结果取反。首先,它将操作数转换为Number值,然后取反该值。

    -"23" // -23
    

    字符串“23”将转换为Number类型,得到23.然后,正数将会转换为复数形式-23.

    -{} // NaN
    -null // -0
    -undefined // NaN
    -{ valueOf: () => 67 } // -67
    -"nnamdi45" // NaN
    

    如果转换为数值的结果为NaN,则不会取反。

    取负+0产生-0,取负-0产生+0。

    - +0 // -0
    - -0 // 0
    

    Exponentiation ** operator

    该运算符用于查找数字的指数。数字的幂上升到一个确定的级。
    在数学中,如果2的3次方(找到2的指数),则意味着将2乘以三次:

    2 * 2 * 2
    

    我们可以用**运算符在JS中相同的操作:

    2 ** 3 // 8
    9 ** 3 // 729
    

    Conclusion

    😀JS中有很多很棒的功能。即将推出更多功能,将不断更新。

    如果拥有或发现了JS很少使用的任何功能,可以在评论中回复。很高兴能知道这些😀。

    翻译结束!

    相关文章

      网友评论

          本文标题:11+ JavaScript Features You’ve P

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