学习记录整理于:https://chinese.freecodecamp.org/learn.
一、变量 1、声明变量 在计算机科学中,数据就是一切,它对于计算机意义重大。 JavaScript 提供八种不同的数据类型,它们是 undefined
(未定义)、null
(空)、boolean
(布尔型)、string
(字符串)、symbol
、number
(数字)、bigint
(可以表示任意大的整数)和 object
(对象)。
例如,计算机区分数字,例如 12
,和由字符组成的字符串 strings
,例如 "12"
、"dog"
或 "123 cats"
。 计算机可以对数字执行数学运算,但不能对字符串执行数学运算。
变量允许计算机以一种动态的形式来存储和 *** 作数据, 即通过 *** 作指向数据的指针而不是数据本身来实现。 以上八种数据类型中的任何一种都可以存储到一个变量中。
变量非常类似于你在数学中使用的 x、y 变量,都是以一个简单命名的名称来代替我们赋值给它的数据。 计算机中的变量与数学中的变量不同的是,计算机可以在不同的时间存储不同类型的变量。
通过在变量前面使用关键字 var
,声明一个变量,例如:
var myName;
上面代码的意思是创建一个名为 myName
的变量。 在 JavaScript 中我们以分号结束语句。 变量名称可以由数字、字母、美元符号 $
或者下划线 _
组成,但是不能包含空格或者以数字为开头。
在 JavaScript 中,你可以使用赋值(assignment)运算符 (=
)将值存储在变量中。
myVar = 5;
这条语句把 Number
类型的值 5
赋给变量 myVar
。
在将值赋给运算符左侧的变量之前,将先执行 =
运算符右侧的所有运算。
var a;
a=7;
首先,此代码创建一个名为 myVar
的变量。 然后,数值 5
被赋给变量 myVar
。 现在,如果 myVar
再次出现在代码中,程序将会将它视为 5
。
在使用赋值运算符赋予变量某个值后,可以使用赋值运算符将该变量的值赋给另一个变量。
var myVar;
myVar = 5;
var myNum;
myNum = myVar;
以上代码声明了一个没有初始值的变量 myVar
,然后给它赋值为 5
。 紧接着,又声明了一个没有初始值的变量 myNum
。 然后,变量 myVar
的内容(也就是 5
)被赋给了变量 myNum
。 现在,变量 myNum
的值也为 5
。
如果要初始化变量,即可赋值为0。如:
var myVar = 0;
4、声明字符串变量
之前,使用以下代码声明变量:
var myName;
&emp;但是也可以像这样声明一个字符串变量:
var myName = "your sky";
"your sky"
被称为 string literal。 字符串文字或字符串是用单引号或双引号括起来的一系列零个或多个字符。
注意:对于理解初始化的变量,当 JavaScript 中的变量被声明的时候,程序内部会给它一个初始值 undefined
。 当对一个值为 undefined
的变量进行运算 *** 作的时候,算出来的结果将会是 NaN
,它的意思是 “Not a Number”。 当用一个值是 undefined
的变量来做字符串拼接 *** 作的时候,它会转换成字符串(string)undefined
。
例如:var a;
var b;
var c;
a=5;
b=10;
c='I am';
a = a + 1;
b = b + 5;
c = c + " sky!";
定义 3 个变量 a
、b
、c
,并且分别给他们赋值,这样它们值就不会是 undefined
了。
使用 var
关键字声明变量的最大问题之一是可以轻松覆盖变量声明:
var camper = "James";
var camper = "David";
console.log(camper);
在上面的代码中,camper
变量最初声明为 James
,然后被覆盖为 David
。 然后控制台显示字符串 David
。
在小型应用程序中,可能不会遇到此类问题。 但是随着代码库变大,可能会意外地覆盖一个你不打算覆盖的变量。 由于此行为不会引发错误,因此搜索和修复错误变得更加困难。
后面将引入了一个名为 let
的关键字,这是对 JavaScript 的一次重大更新,以解决与 var
关键字有关的潜在问题。
如果将上面代码中的 var
替换为 let
,则会导致错误:
let camper = "James";
let camper = "David";
该错误可以在浏览器控制台中看到。
所以不像 var
,当你使用 let
时,同名的变量只能声明一次。
const
关键字声明只读变量
关键字 let
并不是声明变量的唯一新方法。 在 ES6
中,你还可以使用 const
关键字声明变量。
const
具有 let
的所有出色功能,另外还有一个额外的好处,即使用 const
声明的变量是只读的。 它们是一个常量值,这意味着一旦一个变量被赋值为 const
,它就不能被重新赋值:
const PET = "Cats";
PET = "Dogs";
由于重新分配 PET
的值,控制台将显示错误。
应该始终使用 const
关键字命名不想重新分配的变量。 这有助于避免给一个常量进行额外的再次赋值。
注意: 通常,开发者会用大写字母作为常量标识符,用小写字母或者驼峰命名作为变量(对象或数组)标识符。 在后面有关对象、数组以及不可变和可变值的更多信息。 同样在后面将看到大写、小写或驼峰式变量标识符的示例。
二、运算 1、基本运算 JavaScript 中,我们通过符号 +
来进行加法运算。
代码示例:
const myVar = 5 + 10;
现在,变量 myVar
的值为 15
。
减法,乘法,除法同理。
求余运算:求余运算符 %
返回两个数相除得到的余数
5 % 2 = 1 因为
Math.floor(5 / 2) = 2 (商)
2 * 2 = 4
5 - 4 = 1 (余数)
2、数字递增
i++;
等效于:
i = i + 1;
减法同理。
复合运算:在编程中,通常通过赋值来修改变量的内容。 记住,赋值时 JavaScript 会先计算等号右边的内容,所以我们可以写这样的语句:
myVar = myVar + 5;
给 myVar
加上 5
。 这是最常见的运算赋值语句,即先运算、再赋值。还有一类 *** 作符是一步到位,既做运算也赋值的。
其中一种就是 +=
运算符。
let myVar = 1;
myVar += 5;
console.log(myVar);
控制台将会显示 6
。
其余的减法乘法除法类似
3、创建小数可以把小数存储到变量中。 小数有时候也被称作浮点数或者 floats。
提示: 不是所有的实数都可以用浮点数(floating point)来表示。 因为可能产生四舍五入的错误。
如:
const ourDecimal = 5.7;
const myDecimal=5.7;
同样的,小数也能进行加减乘除。
三、字符串 1、转义字符串中的引号 定义一个字符串必须要用单引号或双引号来包裹它。 那么当你的字符串里面包含引号 "
或者 '
时该怎么办呢?
在 JavaScript 中,可以通过在引号前面使用反斜杠(\
)来转义引号。
例如:
const mySky = "I am a \"double quoted\" string inside \"double quotes\"."
则表示:
mySky = "I am a "double quoted" string inside "double quotes"."
2、用单引号引用字符串
JavaScript 中的字符串可以使用开始和结束都是同类型的单引号或双引号表示。 与其他一些编程语言不同的是,单引号和双引号的功能在 JavaScript 中是相同的。
const doubleQuoteStr = "This is a string";
const singleQuoteStr = 'This is also a string';
当你需要在一个字符串中使用多个引号的时候,你可以使用单引号包裹双引号或者相反。 常见的场景比如在字符串中包含对话的句子需要用引号包裹。 另外比如在一个包含有 标签的字符串中,标签的属性值需要用引号包裹。
const conversation = 'Finn exclaims to Jake, "Algebraic!"';
然而,如果你需要在其中使用外面的引号,这就成为一个问题。 记住,一个字符串在开头和结尾处有相同的引号。 要知道,字符串在开头和结尾都有相同的引号,如果在中间使用了相同的引号,字符串会提前中止并抛出错误。
3、转义字符引号不是字符串中唯一可以被转义(escaped)的字符。 使用转义字符有两个原因:
- 首先是可以让你使用无法输入的字符,例如退格。
- 其次是可以让你在一个字符串中表示多个引号,而不会出错。
我们在之前的挑战中学到了这个。
代码 | 输出 |
---|---|
\' | 单引号 |
\" | 双引号 |
\ | 反斜杠 |
\n | 换行符 |
\r | 回车符 |
\t | 制表符 |
\b | 退格 |
\f | 换页符 |
在 JavaScript 中,当 +
*** 作符被用于一个 String
类型的值的时候,它被称作拼接 *** 作符。 你可以通过拼接其他字符串来创建一个新的字符串。
例如:
'My name is sky,' + ' I maintain.'
提示: 注意空格。 拼接 *** 作不会在两个字符串之间添加空格。所以,如果想加上空格的话,你需要自己在字符串里面添加。
例如:
const ourStr = "I come first. " + "I come second.";
字符串 I come first. I come second.
将显示在控制台中。
同样的,可以使用+= 运算符连接字符串。
对于那些被分割成几段的长的字符串来说,这一 *** 作是非常有用的。
提示: 注意空格。 拼接 *** 作不会在两个字符串之间添加空格,所以,如果想要加上空格的话,你需要自己在字符串里面添加。
例如:
let ourStr = "I come first. ";
ourStr += "I come second.";
ourStr 为 I come first. I come second.
当然,我们也可以用变量构造字符串。
例如:
const ourName = "freeCodeCamp";
const ourStr = "Hello, our name is " + ourName + ", how are you?";
ourStr` 值为 `Hello, our name is freeCodeCamp, how are you?
同样对于追加字符串,可以用多行字符串字面量构建单个字符串一样,还可以使用加且赋值(+=
)运算符将字符串追加到字符串的末尾。
示例:
const anAdjective = "awesome!";
let ourStr = "freeCodeCamp is ";
ourStr += anAdjective;
ourStr
值为 freeCodeCamp is awesome!
。
可以通过在字符串变量或字符串后面写上 .length
来获得 String
的长度。
console.log("Alan Peter".length);
字符串 10
将会出现在控制台中。
例如,如果我们创建了一个变量 const Name = "Ada"
,我们可以通过使用 Name.length
找出字符串 Ada
的长度属性。
同样,通过在[]加入索引,可以寻找所需字符。可以使用方括号来获得一个字符串中的其他位置的字符。
请记住,程序是从 0
开始计数,所以获取第一个字符实际上是第零个字符串。
例如:
const firstName = "Ada";
const secondLetterOfFirstName = firstName[1];
secondLetterOfFirstName
值应该为字符串 d
。
要获取字符串的最后一个字符,可以用字符串的长度减 1 的索引值。
例如,如果 const firstName = "Ada"
,则可以使用 firstName[firstName.length - 1]
获取字符串最后一个字母的值。
示例:
const firstName = "Ada";
const lastLetter = firstName[firstName.length - 1];
lastLetter
值为字符串 a
。倒数n个同理。
而且字符串具有不变性,在 JavaScript 中,字符串(String
)的值是不可变的(immutable),这意味着一旦字符串被创建就不能被改变。
例如,下面的代码:
let myStr = "Bob";
myStr[0] = "J";
这样是不会把变量 myStr
的值改变成 Job
的,因为变量 myStr
是不可变的。 注意,这并不意味着 myStr
永远不能被改变,只是字符串字面量 string literal 的各个字符不能被改变。 改变 myStr
的唯一方法是重新给它赋一个值,例如:
let myStr = "Bob";
myStr = "Job";
6、数组
使用数组(array
),我们可以在一个地方存储多个数据。
以左方括号开始定义一个数组,以右方括号结束,里面每个元素之间用逗号隔开,例如:
const sandwich = ["peanut butter", "jelly", "bread"];
我们可以使用索引(indexes)来访问数组中的数据。
数组索引与字符串一样使用方括号来表示,不同的是,它们不是指定字符,而是指定数组中的一个条目。 数组索引与字符串索引一样是从 0 开始(zero-based)的,所以数组中第一个元素的索引编号是 0
。
例:
const array = [50, 60, 70];
array[0];
const data = array[1];
现在 array[0]
的值是 50
, data
的值为 60
.
与字符串不同,数组的条目是 可变的 并且可以自由更改,即使数组是用 const
声明的。
例:
const ourArray = [50, 40, 30];
ourArray[0] = 15;
ourArray
值为 [15, 40, 30]
。
我们可以把多维数组看作成是数组中的数组。 使用方括号表示法访问数组时,第一个方括号访问的是数组的最外层(第一层),第二个方括号访问的是数组的第二层,以此类推。
例如:
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[[10, 11, 12], 13, 14]
];
arr[3];
arr[3][0];
arr[3][0][1];
arr[3]
为 [[10, 11, 12], 13, 14]
,arr[3][0]
为 [10, 11, 12]
,并且 arr[3][0][1]
为 11
。
一个将数据添加到数组末尾的简单方法是 push()
函数。
.push()
接受一个或多个参数(parameters),并把它压入到数组的末尾。
示例:
const arr1 = [1, 2, 3];
arr1.push(4);
const arr2 = ["Stimpson", "J", "cat"];
arr2.push(["happy", "joy"]);
arr1
现在值为 [1, 2, 3, 4]
,arr2
值为 ["Stimpson", "J", "cat", ["happy", "joy"]]
。改变数组中数据的另一种方法是用 .pop()
函数。
.pop()
函数用来d出一个数组末尾的值。 我们可以把这个d出的值赋给一个变量存储起来。 换句话说就是 .pop()
函数移除数组末尾的元素并返回这个元素。
数组中任何类型的元素(数值,字符串,甚至是数组)都可以被d出来 。
const threeArr = [1, 4, 6];
const oneDown = threeArr.pop();
console.log(oneDown);
console.log(threeArr);
第一个 console.log
将显示值 6
,第二个将显示值 [1, 4]
。
.shift()
了的工作原理就像 .pop()
,但它移除的是第一个元素,而不是最后一个。
示例:
const ourArray = ["Stimpson", "J", ["cat"]];
const removedFromOurArray = ourArray.shift();
removedFromOurArray值为 `Stimpson`,`ourArray` 值为 `["J", ["cat"]]
unshift
(移入)一个元素到数组的头部。
.unshift()
函数用起来就像 .push()
函数一样,但不是在数组的末尾添加元素,unshift()
在数组的头部添加元素。
示例:
const ourArray = ["Stimpson", "J", "cat"];
ourArray.shift();
ourArray.unshift("Happy");
在 shift
、ourArray
后值为 ["J", "cat"]
。 在 unshift
、ourArray
后值为 ["Happy", "J", "cat"]
。
在 JavaScript 中,我们可以把代码的重复部分抽取出来,放到一个函数 (functions)中。
举个例子:
function functionName() {
console.log("Hello World");
}
你可以通过函数名加上后面的小括号来调用(invoke)这个函数,就像这样: functionName();
每次调用函数时,它都会在控制台上打印消息 Hello World
。 每次调用函数时,大括号之间的所有代码都将被执行。
函数的参数 (parameters)在函数调用中充当传入函数的输入占位符(也叫形参)。 函数调用时,参数可以为一个或多个。 调用函数时输入(或传递 “passed”)的实际值被称为参数(arguments)。
这是带有两个参数的函数,param1
和 param2
:
function testFun(param1, param2) {
console.log(param1, param2);
}
然后我们可以调用 testFun
,就像这样: testFun("Hello", "World");
。 我们传入了两个字符串参数, Hello
和 World
。 在函数中,param1
等于字符串 Hello
以及 param2
等于字符串 World
。 请注意,testFun
函数可以多次调用,每次调用时传递的参数会决定参数的实际值。
可以通过函数的参数(arguments)把值传入函数, 也可以使用 return
语句把数据从一个函数中传出来。
示例
function plusThree(num) {
return num + 3;
}
const answer = plusThree(5);
answer
的值为 8
。
plusThree
带有一个参数(argument)num
,并返回(return)一个等于 num + 3
的值。
在 JavaScript 中,作用域涉及到变量的作用范围。 在函数外定义的变量具有 全局 作用域。 这意味着,具有全局作用域的变量可以在代码的任何地方被调用。
未使用 let
或 const
关键字声明的变量会在 global
范围内自动创建。 当在代码其他地方无意间定义了一个变量,刚好变量名与全局变量相同,这时会产生意想不到的后果。 你应该总是用 let
或 const
声明你的变量。
在一个函数内声明的变量,以及该函数的参数都具有局部(local)作用域。 这意味着它们只在该函数内可见。
这是在函数 myTest
内声明局部变量 loc
的例子:
function myTest() {
const loc = "foo";
console.log(loc);
}
myTest();
console.log(loc);
myTest()
函数调用将在控制台中显示字符串 foo
。 console.log(loc)
行(在 myTest
函数之外)将抛出错误,因为 loc
未在函数之外定义。
一个程序中有可能具有相同名称的局部变量 和全局变量。 在这种情况下,局部变量将会优先于全局变量。
下面为例:
const someVar = "Hat";
function myFun() {
const someVar = "Head";
return someVar;
}
函数 myFun
将会返回字符串 Head
,因为局部变量的优先级更高。
函数一般用 return
语句来返回值,但这不是必须的。 在函数没有 return
语句的情况下,当你调用它时,该函数会执行内部代码,返回的值是 undefined
。
示例
let sum = 0;
function addSum(num) {
sum = sum + num;
}
addSum(3);
addSum
是一个没有 return
语句的函数。 该函数将更改全局变量 sum
,函数的返回值为 undefined
。
给 ourDog
添加一个属性 bark
:
ourDog.bark = "bow-wow";
或者
ourDog["bark"] = "bow-wow";
现在,当我们执行 ourDog.bark
时,就能得到他的叫声,bow-wow
。
例如:
const ourDog = {
"name": "Camper",
"legs": 4,
"tails": 1,
"friends": ["everything!"]
};
ourDog.bark = "bow-wow";
2、访问对象
访问对象属性有两种方式:点号表示法(.
)和方括号表示法([]
)。
如果我们已经提前知道要访问的属性名,使用点号表示法是最方便的。
这里是一个用点符号(.
)读取对象属性的示例:
const myObj = {
prop1: "val1",
prop2: "val2"
};
const prop1val = myObj.prop1;
const prop2val = myObj.prop2;
prop1val
的值将为字符串 val1
,并且prop2val
的值将为字符串 val2
。
访问对象属性的第二种方式是方括号表示法([]
)。 如果你想访问的属性名中包含空格,就必须使用方括号表示法来获取它的属性值。
当然,如果属性名不包含空格,也可以使用方括号表示法。
这是一个使用方括号表示法读取对象属性的例子:
const myObj = {
"Space Name": "Kirk",
"More Space": "Spock",
"NoSpace": "USS Enterprise"
};
myObj["Space Name"];
myObj['More Space'];
myObj["NoSpace"];
myObj["Space Name"]
将会是字符串 Kirk
,myObj['More Space']
将会是字符串 Spock
,并且myObj["NoSpace"]
将会是字符串 USS Enterprise
。
还可以访问对象上作为变量值存储的属性。 当你需要遍历对象的所有属性,或者根据一个变量的值查找对应的属性值时,这种写法尤其适用。
以下是一个使用变量来访问属性的例子:
const dogs = {
Fido: "Mutt",
Hunter: "Doberman",
Snoopie: "Beagle"
};
const myDog = "Hunter";
const myBreed = dogs[myDog];
console.log(myBreed);
字符串 Doberman
将会出现在控制台中。
使用这一概念的另一种情况是:属性的名字是在程序运行期间动态收集得到的。如下所示:
const someObj = {
propName: "John"
};
function propPrefix(str) {
const s = "prop";
return s + str;
}
const someProp = propPrefix("Name");
console.log(someObj[someProp]);
someProp
的值将为字符串 propName
,并且字符串 John
将会出现在控制台中。
注意,当使用变量名访问属性时,我们没有使用引号包裹它,因为我们正在使用的是变量的值,而不是变量的名字。
3、属性创建了 JavaScript 对象后,你可以随时更新它的属性,就像更新任何其他变量那样。 你可以使用点或中括号 *** 作符来更新。
举个例子,让我们看看 ourDog
:
const ourDog = {
"name": "Camper",
"legs": 4,
"tails": 1,
"friends": ["everything!"]
};
既然他是一个特别愉快的狗,让我们将他的名字更改为字符串 Happy Camper
。 这有两种方式来更新对象的 name 属性: ourDog.name = "Happy Camper";
或 ourDog["name"] = "Happy Camper";
。更新后,ourDog.name
的值就不再是 Camper
,而是 Happy Camper
。
也可以像更改属性一样给 JavaScript 对象添加属性。
这里展示了如何给 ourDog
添加一个属性 bark
:
ourDog.bark = "bow-wow";
或者
ourDog["bark"] = "bow-wow";
现在,当我们执行 ourDog.bark
时,就能得到他的叫声,bow-wow
。
例如:
const ourDog = {
"name": "Camper",
"legs": 4,
"tails": 1,
"friends": ["everything!"]
};
ourDog.bark = "bow-wow";
同样可以删除对象的属性,例如:
delete ourDog.bark;
有时可能希望将数据存储在一个灵活的数据结构(Data Structure)中。 JavaScript 对象是一种灵活的数据结构。 它可以储存字符串(strings)、数字(numbers)、布尔值(booleans)、数组(arrays)、函数(functions)和对象(objects)以及这些值的任意组合。
这是一个复杂数据结构的示例:
const ourMusic = [
{
"artist": "Daft Punk",
"title": "Homework",
"release_year": 1997,
"formats": [
"CD",
"Cassette",
"LP"
],
"gold": true
}
];
这是一个包含一个对象的数组。 该对象有关于专辑的各种元数据。 它也有一个嵌套的 formats
数组。 可以将专辑添加到顶级数组来增加更多的专辑记录。 对象将数据以一种键 - 值对的形式保存。 在上面的示例中,"artist": "Daft Punk"
有一个键为 artist
值为 Daft Punk
的属性。
可以通过连续使用点号表示法和方括号表示法来访问对象的嵌套属性。
这是一个嵌套对象:
const ourStorage = {
"desk": {
"drawer": "stapler"
},
"cabinet": {
"top drawer": {
"folder1": "a file",
"folder2": "secrets"
},
"bottom drawer": "soda"
}
};
ourStorage.cabinet["top drawer"].folder2;
ourStorage.desk.drawer;
ourStorage.cabinet["top drawer"].folder2
将会是字符串 secrets
,并且 ourStorage.desk.drawer
将会是字符串 stapler
。
与访问嵌套对象类似,数组的方括号可以用来对嵌套数组进行链式访问。
下面是访问嵌套数组的例子:
const ourPets = [
{
animalType: "cat",
names: [
"Meowzer",
"Fluffy",
"Kit-Cat"
]
},
{
animalType: "dog",
names: [
"Spot",
"Bowser",
"Frankie"
]
}
];
ourPets[0].names[1];
ourPets[1].names[0];
ourPets[0].names[1]
应该是字符串 Fluffy
, 并且 ourPets[1].names[0]
应该是字符串 Spot
。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)