JavaScript 的 OMG - 第 1 部分






4.49/5 (12投票s)
这是关于 JavaScript 中一些“不那么明显”的内容系列的第 1 部分……从初学者到专家!
引言
说到 JavaScript,它无疑是一门与众不同的语言。编写代码的结果不像 C#/Java 等语言那样“显而易见”。JavaScript 是人们在 90 年代末,也就是早期互联网时代所喜爱的语言。然后多年来,它被严重忽视,被人们对“服务器”端脚本/语言的喜爱所掩盖。然后,JavaScript 迎来了一个复兴时代,随着 Ajax/Angular JS/Backbone JS/Node JS 等技术的出现,JavaScript 现在正在以同样的方式回馈所有其他语言。人们现在在服务器端、客户端以及应用程序的任何一端编写 JavaScript。
你可能同意或不同意,但在我看来,JavaScript 经历的各个阶段使其成为一门如此独特的语言。一门曾经被认为只能在浏览器中显示有趣提示的语言,现在却被用来编写功能齐全的服务器端代码和前端代码——谁能想到呢?至少我没想到:)
背景
本系列的目的是收集你在编写 JavaScript 代码时可能遇到或可能发生的所有“不那么明显”的事情。如果你是 JavaScript 的初学者,我相信你在编写核心 JavaScript 代码时一定也经历过这些“哦,这太明显了”的时刻。
让我们分享并收集起来吧!
JavaScript OMG #1 - “JavaScript 中变量的普遍性”
听说过作用域吗?作用域就像代码中某个对象/变量的可视性和生命周期。在 C# 这样的服务器端语言中,在方法内声明的变量具有块级作用域。我说的“块级作用域”是什么意思?让我们看一个例子。
当你尝试编译时,Visual Studio 会告诉你一些你不想听到的消息
“当前上下文中不存在名称‘bar’”
这就是 JavaScript 的强大之处……看看吧!
你认为上面这个 JavaScript 函数被调用时会做什么?
“OMG”——它能工作(没什么大不了的——JavaScript 里一切都能工作……嘘!;))
控制台上的结果如下
上面的代码在 C# 这样的静态类型语言中将无法工作,因为编译器不确定‘bar
’是否会声明(因为它取决于‘if
’条件是否为 true
)。
发生了什么?JavaScript 疯了吗?不!它没疯。这是 OMG!尽情享受吧!
在 JavaScript 世界里,有一个叫做**“变量提升”**(Hoisting 的意思是“举起”)的概念。
在函数内部或全局(我将在后面的文章中讨论全局),所有变量声明都会“飞”到函数顶部,位于函数第一行代码的上方。这意味着当我们编写这段代码并调用函数时,所有变量声明都会在其作用域内被提升。我们都知道在函数内部定义的变量的作用域就是函数本身。所以,无论你在哪里“声明”变量,我不是说赋值,我说的是无论你在哪里“声明”变量,都不重要,所有声明都会“飞”到其作用域的顶部,在这个例子中是函数 Foo( )
的顶部,所以变量 FooFoo
和 bar
在顶部被声明了,因此在任何地方都可见。
引用如果 if 条件失败了会怎么样?bar 的赋值永远不会发生,函数将打印
10
未定义
因为 bar 的值永远不会被定义。
JavaScript OMG #2 - “Truthy/Falsy”
你知道布尔数据类型是什么吗?在服务器端语言中,它可以包含 TRUE
或 FALSE
值。在某些数据库中,这种数据类型被定义为位,可以容纳 1
(表示 true)或 0
(表示 false),这对于 MS SQL Server 来说是真的,因为没有布尔数据类型,位 datatype
在那里可以正常工作。
所以 true 是 TRUTHY,false 是 FALSY?……谁知道呢;)
在 C#/Java 等流行语言中,条件需要一个必须返回布尔结果的表达式。所以如果表达式返回‘true
’,条件就会执行,否则它会进入‘else
’块(如果定义了)。
让我们看一个简单的 C# 例子
int RoleId = GetRoleId(); // Suppose the method GetRoleId() returns the RoleId
if(RoleId==10) // the expression RoleId==10 eventually converts to a true or false
{
// program flow comes here if the expression evaluates to 'true'
}
else
{
// program flows comes here if the expression evaluates to 'false'
}
让我们看另一个简单的 C# 例子
int[] BookId = {4,3,6,25};
if(BookId.Length>3 && BookId.Max()>20)
{
// Do something only if the expression BookId.Length>3 && BookId.Max()>20 converts to a 'true'
}
在 JavaScript 中,正如你可能预料到的,情况有所不同。JavaScript 可以在‘if
’条件中容纳布尔值以外的其他值。这些值需要是“Truthy”或“Falsy”。
看看下面的 JavaScript 代码
var name = " Some good boi";
if(name) // name is 'string' here
{
console.log("name is truthy at the moment");
}
//Outputs:
"name is truthy at the moment"
如果传递给‘if
’语句的表达式/变量是“某个东西”,字面意义上的某个东西!JavaScript 的‘if
’语句会考虑它并跳转到‘if
’语句内部。所以那个“某个东西”必须是**Truthy** 值。以下所有值在 JavaScript 中都被视为‘falsy’
false
(布尔值false
,不是字符串‘false
’)0
(数字零)""
(空字符串)null
- 未定义
- NaN(一个特殊的数字值,表示非数字!)
除了上述值之外的所有值都被视为‘truthy’,并会使‘if
’条件成功执行。
几个快速示例
var totalPoint = 10;
var extraPoint ; // if value is not defined it will have 'undefined' by default in JS
if(totalPoint && extraPoint) // so a TRUTHY (totalPoint) AND a FALSY (extraPoint) = FALSY
{
console.log('Student is a geek');
}
if(totalPoint || extraPoint)
{
console.log('Student is average')
}
// Output
Student is average
同样,
var totalPoint = 10;
var extraPoint= 40; // now it has some value so it is TRUTHY
if(totalPoint && extraPoint) // so a TRUTHY (totalPoint) AND a TRUTHY (extraPoint) = TRUTHY
{
console.log('Student is a geek');
}
if(totalPoint || extraPoint)
{
console.log('Student is average')
}
//Output
Student is a geek
Truthy/Falsy 概念的另一个用途
JavaScript 使用 Truthy/Falsy 概念为变量设置默认值。看看
var config;
var logConfig = config || {};
// the above code translates to,
// if config variable has something(TRUTHY), give it to logConfig else
// if config has nothing/not initialized/undefined (FALSY), give a new object literal to logConfig
同样,另一个例子……
var amount;
var extraAmount = 100;
var finalAmount = ( amount && extraAmount )? 50:100;
// The above line translates to if both 'amount' and 'extraAmount' are defined(TRUTHY),
// then finalAmount will be //50 else 100
console.log(finalAmount);
//Output
100
更多 OMG 即将到来……
阅读这篇文章,你学到了什么有趣/好玩/令人恼火的东西吗?
我将在 JavaScript OMG 的每一集中发布至少 2 或 3 个 OMG。如果你从中有所收获,请随时表达。
从纽约市祝你有个美好的一天!