OMG,这些鲜为人知的JavaScript 特性!

简介: javaScript 通常被认为是最容易入门的语言,也是最难掌握的语言,我完全同意。这是因为 JavaScript 是一种非常古老且非常灵活的语言,它有着了神秘的语法和过时的特性。我已经使用 JavaScript 很多年了,直到现在,我偶尔会发现一些隐藏的语法或技巧,这些是我以前不知道的。虽然这些特性可能不太为人所知,但它们仍然是众所周知的。



文中的 指原文作者

javaScript 通常被认为是最容易入门的语言,也是最难掌握的语言,我完全同意。这是因为 JavaScript 是一种非常古老且非常灵活的语言,它有着了神秘的语法和过时的特性。我已经使用 JavaScript 很多年了,直到现在,我偶尔会发现一些隐藏的语法或技巧,这些是我以前不知道的。虽然这些特性可能不太为人所知,但它们仍然是众所周知的。



注意:这里没有包括变量的提升、闭包、代理、原型继承、异步等待、生成器等。

void操作符


JavaScript 有一个一元 void 操作符。你可能见过它被用作 void(0) 或 void 0。void的作用便是返回undefined,在它右边的操作数会正常计算,但是无论结果是什么,void都会返回undefined。使用“0”只是一种惯例。不必使用' 0 ',它可以是任何有效的表达式,如void <表达式>,它仍然返回未定义的。



// void operator
void 0                  // returns undefined
void (0)                // returns undefined
void 'abc'              // returns undefined
void {}                 // returns undefined
void (1 === 1)          // returns undefined
void (1 !== 1)          // returns undefined
void anyfunction()      // returns undefined


为什么要创建一个特殊的关键字来返回undefined而不是仅仅返回undefined? 听起来有点多余,不是吗?🚩 有趣的事实

实际上,在ES5之前,在大多数浏览器中,可以为原始的 undefined = "abc"分配一个新值。所以,在那些日子里,使用void是一种确保始终返回 undefine 的原始值的方法。


构造函数括号是可选的


是的,我们在调用构造函数时在类名后添加的括号——完全可选!😮(前提是不需要将任何参数传递给构造函数)


下面的两种代码风格都被认为是有效的 JS 语法而且结果都是一样!



// Constructor with brackets
const date = new Date()
const month = new Date().getMonth()
const myInstance = new MyClass()
// Constructor without brackets
const date = new Date
const month = (new Date).getMonth()
const myInstance = new MyClass


可以省略 IIFE(立即执行函数)的括号


IIFE (立即调用的函数表达式)的语法对我来说总是有点奇怪,为什么要有那么多的括号?


实际上,这些额外的括号只是为了告诉JavaScript解析器,即将解析的的代码是一个函数表达式,而不是函数。知道了这一点,你可以想象,有很多方法可以省略那些额外的括号,仍然可以使用 IIFE 有效的工作。



// IIFE
(function () {
  console.log('正常形式的 IIFE 调用')
})()
// 清爽的 IIEF 
void function() {
  console.log('酷酷的 IIFE 调用')
}()


void 操作符告诉解析器代码是函数表达式。因此,我们可以跳过函数定义周围的括号。你猜怎么着? 我们可以使用任何一元运算符(void, +, !, -等等),这仍然有效!


这是不是比原始的写法简单而且 B 格多了呢?


但是,如果你是一个敏锐的观察者,你可能会想,一元运算符不会影响 IIFE 返回的结果吗?


它会影响结果。但好消息是,如果你只要的返回的结果并将其存储在某个变量中,那么就不需要额外的括号。



with 的声明


JavaScript 有一个with语句块, with 实际上是JS中的关键字。 with 块的语法如下:



with 语句可以方便地用来引用某个特定对象中已有的属性,但是不能用来给对象添加属性。要给对象创建新的属性,必须明确地引用该对象。



🚩 有趣的事实

with 块看起来很酷,对吧? 它甚至比对象销毁更好。好吧,其实不是。

通常不鼓励使用 with 语句,因为它已被弃用,在严格模式下完全禁止。事实证明,使用 with 块会增加语言中的一些性能和安全性问题。


函数构造器


函数语句不是定义新函数的唯一方法,可以使用function()构造函数和new 操作符动态定义函数。



🚩 有趣的事实

Function 构造函数是 JavaScript 中所有构造函数的母亲。甚至 Object 的构造函数也是 Function 构造函数。而 Function 自己的构造函数也是 Function 本身。 因此,调用 object.constructor.constructor ...足够多次将最终在 JavaScript 中的任何对象上返回Function构造函数。


函数属性


我们都知道函数是JavaScript中的第一类对象。因此,没有人阻止我们向函数添加自定义属性。在 JS 中这样做是有效的,然而,它很少被使用。


那么我们什么时候要这样做?


这里有一些很好的用例。例如,


可配置函数


假设我们有一个函数叫做 greet。我们希望函数根据不同的地区打印不同的问候消息,这个区域设置也应该是可配置的。我们可以在某个地方维护全局 locale 变量,也可以使用如下所示的函数属性实现该函数



function greet () {
  if (greet.locale === 'ch') {
    console.log('中国,你好')
  } else if (greet.locale === 'jp') {
    console.log('扣你机哇!')
  } else {
    console.log('Hello World')
  }
}
greet() // Hello World
greet.locale = 'ch';
greet() // 中国,你好


具有静态变量的函数


另一个类似的例子。比方说,希望实现一个生成有序数字序列的数字生成器。通常您将使用带有静态计数器变量的 Class 或 IIFE 来跟踪最后一个值。这样我们就限制了对计数器的访问,同时也避免了使用额外的变量污染全局空间。


但是,如果我们希望能够灵活地读取甚至修改计数器,而又不污染全局空间,该怎么办呢?


我们仍然可以创建一个类,有一个计数器变量和一些额外的方法来读取它;或者我们可以偷懒,使用函数自定义的属性。



Arguments 的属性


我相信你们大多数人都知道函数中的arguments对象。它是一个类似数组的对象,可以在所有函数中使用。它具有在调用函数时传递给函数的参数列表。但它也有一些其他有趣的性质:


  • arguments.callee: 当前调用的函数
  • arguments.callee.caller:调用当前函数的函数



注意:虽然ES5禁止在严格模式下使用callee & caller,但在许多编译后的库中仍然很常见。所以,学习它们是值得的。

标记模板字符串


模板字符串文字是ES6中许多很酷的附加内容之一,但是,知道标记模板字符串是比较少的?



标记模板字符串允许你通过向模板字符串添加自定义标记来更好地将模板文字解析为字符串。Tag只是一个解析器函数,它获取字符串模板解释的所有字符串和值的数组,标记函数应返回最终字符串。


在下面的例子中,我们的自定义标记 —— 高亮显示,解释模板文本的值,并将解释后的值包装在结果字符串中,使用<mark>元素进行高亮显示。



Getters & Setters


在大多数情况下,JavaScript对象是简单的。假设我们有一个 user 对象,我们试图使用user访问它的age属性。使用 user.age 得到年龄属性的值,如果没有定义,我们得到未定义的值。


但是,并不一定要这么简单。JavaScript 对象具有 getter 和 setter 的概念。我们可以编写自定义Getter函数来返回我们想要的任何东西,而不是直接返回对象上的值,设置一个值也是一样。


这使我们可以在获取或设置字段时拥有强大的能力,如 virtual fieldsfield validationsside-effects



逗号操作符


JavaScript有一个逗号操作符。它允许我们在一行中用逗号分隔多个表达式,并返回上一个表达式的结果。



在这里,所有表达式都将被求值,结果变量将被赋值给expressionN返回的值。


我们经常在for循环中使用了逗号操作符


for (var a = 0, b = 10; a <= 10; a++, b--)


有时在一行中编写多个语句


function getNextValue() {
    return counter++, console.log(counter), counter
}


或者


const getSquare = x => (console.log (x), x * x)


+ 加号操作符号


想要快速地将字符串转换为数字吗?


只需在字符串前面加上+运算符。加号运算符也适用于负数、八进制、十六进制、指数值。更重要的是,它甚至可以转换 Date 或者 Moment.js对象的时间戳!



!! 操作符


从技术上讲,它不是一个单独的JavaScript操作符。它只是两次使用的 JavaScript 反运算符。


如果表达式为true值,则返回true;否则返回false。



~ 非操作符


让我们面对它——没有人关心位操作符。我们什么时候才能使用它!


这里有一个日常用例是关于波浪号或位非运算符的。


事实证明,当与数字一起使用时,非运算符是有效的 ~N => -(N+1)这个表达式只有在 N为-1时才计算为 “0”。


我们可以通过将~放在theindexOf(…)函数前面来利用这一点,如果项目存在于字符串或数组中,则执行布尔检查。



注意:ES6和ES7分别在字符串和数组中添加了一个新的 .include()方法。当然,这是一种比波浪号操作符更清晰的方法来检查一个项目是否存在于数组或字符串中。

标签 的使用


break和continue语句都可以与lebel语句联合使用,从而返回代码中特定的位置。用于嵌套循环,减少循环次数。



目录
相关文章
|
30天前
|
JavaScript 前端开发 编译器
掌握现代化JavaScript:ECMAScript提案与特性
【10月更文挑战第13天】本文介绍了ECMAScript(ES)的最新提案与特性,包括可选链、空值合并运算符、类字段和顶层Await等。通过跟踪TC39提案、使用Babel或TypeScript、测试兼容性以及逐步迁移,开发者可以高效地采用这些新特性,简化代码、提高开发效率并增强应用功能。文章还提供了实战技巧,帮助开发者在现代Web开发中充分利用这些现代化的特性。
|
1月前
|
JavaScript 前端开发 索引
JavaScript ES6及后续版本:新增的常用特性与亮点解析
JavaScript ES6及后续版本:新增的常用特性与亮点解析
27 4
|
16天前
|
前端开发 JavaScript
JavaScript新纪元:ES6+特性深度解析与实战应用
【10月更文挑战第29天】本文深入解析ES6+的核心特性,包括箭头函数、模板字符串、解构赋值、Promise、模块化和类等,结合实战应用,展示如何利用这些新特性编写更加高效和优雅的代码。
32 0
|
2月前
|
JavaScript 前端开发 Oracle
软件工程师,学习下JavaScript ES6新特性吧
软件工程师,学习下JavaScript ES6新特性吧
43 9
|
3月前
|
Rust JavaScript 前端开发
Rust! 无VDom! 尤雨溪解析 Vue.js 2024 新特性
Rust! 无VDom! 尤雨溪解析 Vue.js 2024 新特性
|
3月前
|
Web App开发 前端开发 JavaScript
[译] JavaScript ES2021 中激动人心的特性
[译] JavaScript ES2021 中激动人心的特性
|
3月前
|
前端开发 JavaScript 开发者
翻天覆地!ES6+新特性大爆发,揭秘JavaScript代码的惊人蜕变!
【8月更文挑战第27天】自ES6标准发布以来,JavaScript新增的特性极大地提升了编程效率并简化了代码。本文重点介绍了五大特性:函数默认参数简化、模板字符串的强大功能、解构赋值的便捷性、箭头函数的简洁之美。这些特性不仅使代码更加简洁、易读,还解决了传统写法中的诸多问题。通过学习和应用这些新特性,开发者可以编写出更高效、更优雅的代码,以应对日益复杂的编程挑战。
66 2
|
3月前
|
JavaScript 前端开发 安全
JS 混淆解析:JS 压缩混淆原理、OB 混淆特性、OB 混淆JS、混淆突破实战
JS 混淆解析:JS 压缩混淆原理、OB 混淆特性、OB 混淆JS、混淆突破实战
166 2
|
3月前
|
JavaScript 前端开发 API
JavaScript特性检测
JavaScript特性检测
|
3月前
|
开发者 图形学 C#
深度解密:Unity游戏开发中的动画艺术——Mecanim状态机如何让游戏角色栩栩如生:从基础设置到高级状态切换的全面指南,助你打造流畅自然的游戏动画体验
【8月更文挑战第31天】Unity动画系统是游戏开发的关键部分,尤其适用于复杂角色动画。本文通过具体案例讲解Mecanim动画状态机的使用方法及原理。我们创建一个游戏角色并设计行走、奔跑和攻击动画,详细介绍动画状态机设置及脚本控制。首先导入动画资源并添加Animator组件,然后创建Animator Controller并设置状态间的转换条件。通过编写C#脚本(如PlayerMovement)控制动画状态切换,实现基于玩家输入的动画过渡。此方法不仅适用于游戏角色,还可用于任何需动态动画响应的对象,增强游戏的真实感与互动性。
97 0