JavaScript基础
变量
变量保存的数据可以在需要时设置、更新或提取。赋给变量的值都有对应的类型。JavaScript
的类型有数字、字符串、布尔值、函数和对象。还有undefined
和null
,以及数组、日期和正则表达式。
注意: JavaScript
是弱类型语言,我们只需要使用var
、let
、const
去声明变量,而不必指定变量类型
在TypeScript中,我们可以在声明变量的时候指定变量的类型。很显然使用Typescript
更加严谨,如Vue、React都已经开始全面拥抱Typescript
了,或许在不久的将来,Typescript
会成为前端编写的主流。但这并不是说JavaScript
就没用了。 在之后的例子,我还是使用JavaScript
。
var num = 1; //{1}
num = 3; //{2}
const price = 1.5; //{3}
const name = 'mark_m'; //{4}
const trueValue = true; //{5}
const nullValue = null; //{6}
let und;
console.log("num:",typeof num,num);
console.log("price:",typeof price,price);
console.log("name:",typeof name,name);
console.log("trueValue:",typeof trueValue,trueValue);
console.log("nullValue:",typeof nullValue,nullValue);
console.log("und:",typeof und,nullValue);
- 在第一行,展示了如何声明一个变量,虽然
var
不是必须的,但最好每次都加上。
注意:在申明变量时最好不要使用var
,尽量使用const
,少使用let
。var
声明的是一个变量,变量本身意味着结构可变,但凡结构可变的数据,其本身就意味着不稳定,也意味着代码设计本身存在的缺陷。
-
在第二行,更新了已有变量。
Js
是弱类型语言,这就意味这可以把申明一个初始化类型为数字的值更新成其他类型的值,这很糟糕。 -
在第三行,声明了一个十进制浮点数
-
在第四行,声明了一个字符串
-
在第五行,声明了布尔值
-
在第六行,声明了
null
-
在第七行,声明了
ubdefined
。
注意:null
表示变量没有值,undefined
表示变量已经被声明,但尚未赋值。
变量作用域
作用域指在编写的算法函数中,我们能访问的变量(在使用时,函数作用域也可以是一个函数)。有本地变量和全局变量两种。
var myVariable = "global";
myOtherVariable = "global";
function myFunction() {
var myVariable = "local";
return myVariable;
}
function myOtherFunction() {
myOtherVariable = "local";
return myOtherVariable;
}
console.log(myVariable); //{1}
console.log(myFunction()); //{2}
console.log(myOtherVariable); //{3}
console.log(myOtherFunction()); //{4}
console.log(myOtherVariable); //{5}
- 行1输出
global
,它是全局变量 - 行2输出
local
,myVariable
是在myFunction
函数中声明的本地变量,所以作用域仅在myFunction
内。 - 行{3}输出
global
,引用了在第二行初始化了的全局变量myOtherVariable
。 - 行{4}输出
local
。在myOtherFunction
函数里,因为没有使
用var
关键字修饰,所以这里引用的是全局变量myOtherVariable
并将它赋值为local
。 - 行{5}输出
local
(因为在myOtherFunction
里修改了
myOtherVariable
的值)。
代码质量可以用全局变量和函数的数量来考量(数量越多越
糟)。因此,尽可能避免使用全局变量。
操作符
在JavaScript
里有算数操作符、赋值操作符、比较操作符、逻辑操作符、位操作符、一元操作符和其他操作符。
var num = 0; //{1}
num = num + 2;
num = num * 3;
num = num / 2;
num++;
num--;
num += 1; //{2}
num -= 2;
num *= 3;
num /= 2;
num %= 3;
console.log("num == 1 : " + (num == 1)); // {3}
console.log("num === 1 : " + (num === 1));
console.log("num != 1 : " + (num != 1));
console.log("num > 1 : " + (num > 1));
console.log("num < 1 : " + (num < 1));
console.log("num >= 1 : " + (num >= 1));
console.log("num <= 1 : " + (num <= 1));
console.log("true && false : " + (true && false)); // {4}
console.log("true || false : " + (true || false));
console.log("!true : " + !true);
- 在行{1},我们用了算数操作符。在下面的表格里,列出了这些操作符
及其描述。
算数操作符 | 描述 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 取余 |
++ | 递增 |
– | 递减 |
- 在行{2},我们使用了赋值操作符,在下面的表格里,列出了赋值操作
符及其描述。
算数操作符 | 描述 |
---|---|
= | 赋值 |
+= | 加/赋值 (x += y) == (x = x + y) |
-= | 减/赋值 (x -= y) == (x = x - y) |
*= | 乘/赋值 (x *= y) == (x = x * y) |
/= | 除/赋值 (x /= y) == (x = x / y) |
%= | 取余/赋值 (x %= y) == (x = x % y) |
- 在行{3},我们使用了比较操作符。在下面的表格里,列出了比较操作
符及其描述
算数操作符 | 描述 |
---|---|
== | 相等 |
=== | 全等 |
!= | 不等 |
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
- 在行{4},我们使用了逻辑操作符。在下面的表格里,列出了逻辑操作
符及其描述。
算数操作符 | 描述 |
---|---|
&& | 与 |
|| | 或 |
! | 非 |
JavaScript
也支持位操作符,如下所示
console.log("5 & 1:", 5 & 1);
console.log("5 | 1:", 5 | 1);
console.log("~ 5:", ~5);
console.log("5 ^ 1:", 5 ^ 1);
console.log("5 << 1:", 5 << 1);
console.log("5 >> 1:", 5 >> 1);
下面的表格对位操作符做了更详细的描述
算数操作符 | 描述 |
---|---|
& | 与 |
或 | |
~ | 非 |
^ | 异或 |
<< | 左移 |
>> | 右移 |
typeof
操作符可以返回变量或表达式的类型。我们看下面的代码:
console.log("typeof num:", typeof num); // typeof num: number
console.log("typeof Packt:", typeof "Packt"); // typeof Packt: string
console.log("typeof true:", typeof true); // typeof true: boolean
console.log("typeof [1,2,3]:", typeof [1, 2, 3]); // typeof [1,2,3]: object
console.log("typeof {name:John}:", typeof { name: "John" }); // typeof {name:John}: object
JavaScript
还支持delete
操作符,可以删除对象里的属性。看看下面的
代码:
var myObj = { name: "John", age: 21 };
delete myObj.age;
console.log(myObj); // 输出对象{name: "John"}
真值和假值
在JavaScript中,true和false有些复杂。在大多数编程语言中,布尔值true
和false
仅仅表示true/false
。在JavaScript
中,如"Packt"
这样的字符串值,也可以看作true。
数值类型 | 转换成布尔值 |
---|---|
undefined | false |
null | false |
布尔值 | true是true,false是false |
数字 | +0、-0和NaN都是false,其他都是true |
字符串 | 如果字符串是空的(长度是0)就是false,其他都是true |
对象 | true |
我们来看一些代码,用输出来验证上面的总结:
function testTruthy(val) {
return val ? console.log("truthy") : console.log("falsy");
}
testTruthy(true); //true
testTruthy(false); //false
testTruthy(new Boolean(false)); //true (对象始终为true)
testTruthy(""); //false
testTruthy("Packt"); //true
testTruthy(new String("")); //true (对象始终为true)
testTruthy(1); //true
testTruthy(-1); //true
testTruthy(NaN); //false
testTruthy(new Number(NaN)); //true (对象始终为true)
testTruthy({}); //true (对象始终为true)
var obj = { name: "John" };
testTruthy(obj); //true
testTruthy(obj.name); //true
testTruthy(obj.age); //false (年龄不存在)
相等操作符(==
和===
)
当使用这两个相等操作符时,可能会引起一些困惑。
使用==
时,不同类型的值也可以被看作相等。这样的结果可能会使部分的JavaScript
开发者感到困惑。用表格分析一下不同类型的值用相等操作符比较后的结果。
类型(x) | 类型(y) | 结果 |
---|---|---|
null | undefined | true |
undefined | null | true |
数字 | 字符串 | x == toNumber(y) |
字符串 | 数字 | toNumber(x) == y |
布尔值 | 任何类型 | toNumber(x) == y |
任何类型 | 布尔值 | x == toNumber(y) |
字符串或数字 | 对象 | x == toPrimitive(y) |
对象 | 字符串或数字 | toPrimitive(x) == y |
如果x
和y
是相同类型,JavaScript
会比较它们的值或对象值。其他没有列在这个表格中的情况都会返回false
toNumber
和toPrimitive
方法是内部的,并根据以下表格对其进行估值。
toNumber
方法对不同类型返回的结果如下:
值类型 | 结果 |
---|---|
undefined | NaN |
null | +0 |
布尔值 | 如果是true,返回1;如果是false,返回+0 |
数字 | 数字对应的值 |
字符串 | 将字符串解析成数字。如果字符串中包含字母,返回NaN;如 果是由数字字符组成的,转换成数字 |
对象 | Number(toPrimitive(vale)) |
toPrimitive
方法对不同类型返回的结果如下:
值类型 | 结果 |
---|---|
对象 | 如果对象的valueOf方法的结果是原始值,返回原始值。如果 对象的toString方法返回原始值,就返回这个值;其他情况 都返回一个错误 |
用例子来验证一下表格中的结果。首先,我们知道下面的代码输出
true(字符串长度大于1):
console.log('packt' ? true : false); // true
那么这行代码的结果呢?
console.log('packt' == true); // false
输出是false,为什么会这样呢?
- 首先,布尔值会被
toNumber
方法转成数字,因此得到packt == 1
。 - 其次,用
toNumber
转换字符串值。因为字符串包含有字母,所以会被转成NaN
,表达式就变成了NaN == 1
,结果就是false
。
那么这行代码的结果呢?
console.log('packt' == false);
输出也是false。步骤如下所示。
- 首先,布尔值会被
toNumber
方法转成数字,因此得到packt == 0
。 - 其次,用
toNumber
转换字符串值。因为字符串包含有字母,所以会被转成NaN
,表达式就变成了NaN == 0
,结果就是false
。
那么===
操作符呢?简单多了。如果比较的两个值类型不同,比较的结
果就是false
。如果比较的两个值类型相同,结果会根据下表判断。
类型(x) | 值 | 结果 |
---|---|---|
数字 | x 和 y 数值相同(但不是NaN) | true |
字符串 | x 和 y 是相同的字符 | true |
布尔值 | x 和 y 都是true或false | true |
对象 | x 和 y 引用同一个对象 | true |
如果x
和y
类型不同,结果就是false
。
我们来看一些例子:
console.log("packt" === true); //false
console.log("packt" === "packt"); //true
var person1 = { name: "John" };
var person2 = { name: "John" };
console.log(person1 === person2); //false,不同的对象