JavaScript 基础

本文将介绍 JavaScript 的输出、数据结构、函数、对象及事件。

一、输出

1. innerHTML

  • 利用 document.getElementById(id) 定位到 HTML 元素
  • innerHTML 属性在 JavaScript 中有双向功能,既可以获取内容,又可以修改内容。这里的内容指的是起始标签和结束标签中的内容。
    • 利用 innerHTML 获取 demo1 元素的内容
    • 利用 innerHTML 修改 demo2 元素的内容
1
2
3
4
5
6
<p id="demo1">你好呀!</p>
<p id="demo2"></p>
<script>
document.getElementById("demo2").innerHTML =
document.getElementById("demo1").innerHTML + "x2";
</script>

你好呀!

2. innerText

与 innerHTML 类似,但用于修改起始标签和结束标签中的文本

3. document.write()

document.write 可以用于在 HTML 文档中直接输出内容。

1
2
3
4
<p>下面将由 document.write 打印出一段文字</p>
<script>
document.write("一段文字");
</script>

下面将由 document.write 打印出一段文字

注意:

若 HTML 文档已经完全加载,则此方法将会覆盖已有的 HTML 。慎用!!!

4. window.alert()

此方法将会调用警示框,可以利用警示框显示数据。

1
<input type="button"value="按钮" onclick="window.alert('这是一个警告框');">

5. console.log()

用于向控制台输出数据。

查看方法:请通过 F12 来激活浏览器控制台,并在菜单中选择“控制台”。

二、数据类型

JavaScript 中有两种类型的值:字面量和变量。

1. 字面量

(1) 数值

(2) 字符串

字符串是文本,由双引号或单引号包围。

若把数值放置在引号中,数值将会被视作字符串。

(3) 数组

JavaScript 中数组由方括号书写,数组的项目由逗号分隔。

1
var cars = ["Porsche", "Volvo", "BMW"];

(4) 对象

JavaScript 中对象由花括号书写,对象的属性由逗号分隔。

1
2
3
4
5
6
var person = {
firstName:"Bill",
lastName:"Gates",
age:62,
eyeColor:"blue"
};

(5) 布尔

布尔值只有两个值:true 或 false

2. 变量

  • JavaScript 中使用 var 关键字来声明变量

    1
    2
    var x;
    x = 7;
  • 声明变量后需要对其赋值,否则其值为 undefined

  • JavaScript 中的变量具有动态类型,因此同一个变量可以被赋予不同类型

3. typeof

typeof 用于判断变量或表达式的类型,它会根据类型返回 number 、string 、object 、boolean 、Undefined 、function

数组和对象都会返回 object

4. constructor

用于返回变量的构造器函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 返回 "function String()  { [native code] }"
"Bill".constructor

// 返回 "function Number() { [native code] }"
(3.14).constructor

// 返回 "function Boolean() { [native code] }"
false.constructor

// 返回 "function Array() { [native code] }"
[1,2,3,4].constructor

// 返回" function Object() { [native code] }"
{name:'Bill', age:62}.constructor

// 返回 "function Date() { [native code] }"
new Date().constructor

// 返回 "function Function(){ [native code] }"
function () {}.constructor

可以通过检查 constructor 的返回值中是否包含指定单词来判断变量的类型。

1
2
3
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}

5. 类型转换

(1) 转换为字符串

用全局方法 String() 或类型方法 toString() 。

(2) 转换为数值

用全局方法 Number() 。

(3) + 运算符

字符串转化为数值
1
+ 字符串
1
2
var y = "5";      // y 是字符串
var x = + y; // x 是数字
数值转化为字符串
1
数值 + 字符串
1
2
var y = 5;      // y 是数字
var x = y + ""; // x 是字符串

三、数值

1. 存储方式

JavaScript 中数值始终是 64 位的浮点数。

2. NaN

NaN 为非数值,表示某个数不是合法数。

可以用 isNaN 来确定某个数是否合法。

3. Infinity 和 -Infinity

用于表示超出范围的数值。

4. 十六进制

0x 为前缀的数值是十六进制的。

不要在数字前面加 0 ,一些 JavaScript 版本会把这些数字解释为八进制

5. 数值对象

可以通过 new 新建数值对象。

1
2
var x = 500;             
var y = new Number(500);

此例中, x 与 y 的值相等,但类型不相等

直接使用数值,不要创建数值对象。

它会拖慢执行速度,使代码复杂化,产生意想不到的结果。

6. 数值方法

(1) toString()

将数值转换为字符串,并返回。

可以用 toString 将数输出为十六进制、八进制或二进制。

1
数值变量名.toString(16|8|2)

(2) toExponential()

将数值转换为字符串,并返回,指数形式。

1
2
3
4
var x = 9.656;
x.toExponential(2); // 返回 9.66e+0
x.toExponential(4); // 返回 9.6560e+0
x.toExponential(6); // 返回 9.656000e+0

(3) toFixed()

将数值转换为字符串,并返回,小数形式。

1
2
3
4
5
var x = 9.656;
x.toFixed(0); // 返回 10
x.toFixed(2); // 返回 9.66
x.toFixed(4); // 返回 9.6560
x.toFixed(6); // 返回 9.656000

(4) toPrecision()

将数值转换为字符串,并返回,可以指定数字的个数。

1
2
3
4
5
var x = 9.656;
x.toPrecision(); // 返回 9.656
x.toPrecision(2); // 返回 9.7
x.toPrecision(4); // 返回 9.656
x.toPrecision(6); // 返回 9.65600

(5) valueOf()

从数值中返回数值,没有理由使用它。

所有 JavaScript 数据类型都有 valueOf() 和 toString() 方法。

(6) Number()

用于把 JavaScript 变量转换为数值。

1
2
3
4
5
6
7
8
9
10
11
12
x = true;
Number(x); // 返回 1
x = false;
Number(x); // 返回 0
x = new Date();
Number(x); // 返回 1404568027739
x = "10"
Number(x); // 返回 10
x = "10 20"
Number(x); // 返回 NaN
x = new Date("2019-04-15");
Number(x); // 返回1506729600000,1970.1.1至该日期的毫秒数

(7) parseInt()

解析字符串并返回数值,允许空格,且只返回首个数字,遇到浮点将转换为 int 型。

1
2
3
4
5
parseInt("10");         // 返回 10
parseInt("10.33"); // 返回 10
parseInt("10 20 30"); // 返回 10
parseInt("10 years"); // 返回 10
parseInt("years 10"); // 返回 NaN

(8) parseFloat()

解析字符串并返回数值,允许空格,且只返回首个数字。

1
2
3
4
5
parseFloat("10");        // 返回 10
parseFloat("10.33"); // 返回 10.33
parseFloat("10 20 30"); // 返回 10
parseFloat("10 years"); // 返回 10
parseFloat("years 10"); // 返回 NaN

(9) 数值属性

数字属性属于名为 Number 的 JavaScript 数字对象包装器,只能通过 Number 访问。

属性 描述
MAX_VALUE 返回 JavaScript 中可能的最大数
MIN_VALUE 返回 JavaScript 中可能的最小数
NEGATIVE_INFINITY 表示负的无穷大(溢出返回)
NaN 表示非数字值(”Not-a-Number”)
POSITIVE_INFINITY 表示无穷大(溢出返回)
1
2
3
4
5
var x = Number.MAX_VALUE;
var x = Number.MIN_VALUE;
var x = Number.NEGATIVE_INFINITY;
var x = Number.NaN;
var x = Number.POSITIVE_INFINITY;

四、字符串

1. 格式

字符串可以使用单引号或双引号包裹。

2. 转义字符

代码 结果
'
"
\\ \

3. 字符串对象

可以通过 new 创建字符串对象:

1
2
var x = "Bill";             
var y = new String("Bill");

此例中, x 与 y 的值相等,但类型不相等

直接使用字符串,不要创建字符串对象。

它会拖慢执行速度,使代码复杂化,产生意想不到的结果。

4. 字符串方法

(1) length()

可以通过内建属性 length 返回字符串的长度。

1
2
var str = "ABCDEFG";
var strlen = str.length;

(2) indexOf()

返回字符串中指定文本首次出现的位置,若未找到,返回 -1 。

可以增加第二个参数,用于指定检索的开始下标。

(3) lastIndexOf()

返回字符串中指定文本最后一次出现的位置,若未找到,返回 -1 。

可以增加第二个参数,用于指定检索的开始下标。

返回字符串中指定文本首次出现的位置。

search 无法设置第二个参数(用于指定检索的开始下标),但可以通过正则表达式进行搜索。

(5) slice()

用于提取字符串中的某一个部分。

1
slice(start, end)
  • 参数可以设为负数,若设为负数,则从后往前计数
  • 若省略第二个参数,将裁剪至末尾

(6) substring()

类似于 slice ,但接受负的参数。

(7) substr()

类似于 slice ,但第二个参数指定的是被提取部分的长度。

1
substr(start, length)

(8) replace()

用另一个值替换字符串中的匹配值。

1
str.replace("匹配值", "另一个值");
  • 并不会改变原先的字符串,需要使用变量接受新字符串
  • 默认只替换首个匹配值
  • 默认只匹配大小写对应的值

可以通过 /g 来对所有匹配值进行替换;

可以通过 /i 来进行忽略大小写的匹配;

(9) toUpperCase() 和 toLowerCase()

用于将字符串转换成大写或小写。

(10) concat()

用于连接字符串。

  • concat 可以用于替代加法运算符,例如:

    1
    2
    var text = "Hello" + " " + "World!";
    var text = "Hello".concat(" ","World!");
  • 不会修改原始字符串,需要用变量接受新字符串

(11) String.trim()

用于删除字符串两端的空白符。

IE8 及以下将不支持此方法,可以使用 replace 和正则表达式代替:

1
str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '')

(12) charAt()

返回字符串中指定下标的字符。

(13) charCodeAt()

返回字符串中指定下标的字符的 unicode 编码。

(14) 属性访问

1
2
var str = "HELLO WORLD";
str[0]; // 返回 H

属性访问有以下几点问题:

  • 不适用于 IE7 及以前的版本
  • 混淆了字符串与数组
  • 如果找不到字符,属性访问会返回 undefined,而 charAt 会返回空字符串
  • 属性访问是只读不可写的

五、数组

1. 创建数组

1
var 数组名 = [元素1, 元素2, ...];

最好不要在最后一个元素之后加逗号,可能存在跨浏览器兼容性问题。

2. 数组对象

可以通过 new 新建数组。

出于简洁、可读性和执行速度的考虑,请不要使用数组对象。

3. 访问数组

访问数组元素
1
数组名[下标]
访问数组
1
数组名

4. 数组实际上是对象

数组是一种特殊类型的对象,在 JavaScript 中对数组使用 typeof 会返回 object 。

5. 数组元素不需要同类型

数组是特殊类型的对象,可以在同一数组中存放不同类型的变量、对象、函数、数组等。

6. 数组与对象的区别

在 JavaScript 中,数组使用数字索引,对象使用命名索引。

7. 如何识别数组

因为 JavaScript 中 typeof 会将数组和对象都视为对象,返回 object ,因此需要其它方法来辨认数组与对象。

(1) 解决方法 1

利用 Array.isArray() ,但此方法不支持老的浏览器。

(2) 解决方法 2

创建自己的 isArray() :

1
2
3
function isArray(x) {
return x.constructor.toString().indexOf("Array") > -1;
}

假如对象原型包含单词 “Array” 则返回 true。

(3) 解决方法 3

假如对象由给定的构造器创建,则 instanceof 运算符返回 true 。

1
fruits instanceof Array

8. 数组方法

(1) toString()

将数组转化为字符串。

(2) join()

将数组转化为字符串,且字符串中各数组元素之间以指定字符串连接。

1
2
var a = [1, 2, 3];
arr.join("-") // "1-2-3"

(3) pop() 和 push()

从数组弹出项目或向数组推入项目。

其中,

  • pop 用于从数组中删除最后一个元素,并返回被删除的值
  • push 用于在数组的末尾添加一个新的元素,并返回新数组的长度

(4) shift()

将首个数组元素删除,并将其它元素依次前移,“位移”到更低的索引。返回被位移出的元素。

(5) unshift()

在数组的开头添加新元素,并将其它元素依次后移,“位移”到更高的索引。返回新数组的长度。

(6) length

可以用 length 获取数组的长度。

1
数组名.length

可以利用 length 向数组中新增元素。

1
数组名[数组名.length] = 新元素;

(7) delect()

可以用 delect 删除数组中的元素。

1
delect 数组名[下标]

delect 会在数组中留下未定义的空洞,请使用 pop 或 shift 替代。

(8) splice()

用于插入数组。

首先在数组中指定位置之后删除给定数量的元素,然后向数组中添加新项(这里的添加是在指定位置之后挤入)。

1
数组名.splice(index, num, 元素列);
  • 第一个参数 index 定义了应添加新元素的位置
  • 第二个参数 num 定义了应删除多少元素
  • 元素列中填入要添加的元素
  • 此方法会返回一个包含已删除项的数组

利用 splice 删除元素

1
数组名.splice(index, num);

(9) concat()

用于连接数组。

通过合并的方式创建新数组。不会更改现有数组,总是返回新数组,可以连接任意数量的数组。

示例:

1
2
3
4
var arr1 = ["aaa", "bbb"];
var arr2 = ["ccc", "ddd", "eee"];
var arr3 = ["fff"];
var myChildren = arr1.concat(arr2, arr3, "ggg");

(10) sort()

用于对数组进行排序,按字典序。

(11) reverse()

用于反转数组中的元素。

可以利用 sort 和 reverse ,对数组进行逆字典序排序。

1
2
数组名.sort();
数组名.reverse();

(12) 数值排序

默认情况下,sort 函数会按照字典序进行排序,这种顺序应用在数字上时,将会发生错误。

例如 25 将会大于 100

可以利用比值函数解决这一问题:

1
数组名.sort(比值函数)

比值函数:

比值函数的目的是定义排序顺序,它应该返回一个负、零或正值。

例如:

1
2
3
function(a, b){
return a-b;
}

(13) Math.max.apply() 和 Math.min.apply()

用于查找数组的最大值和最小值。

1
2
Math.max.apply(null, arr);
Math.min.apply(null, arr);

(14) 自制最大最小值方法

1
2
3
4
5
6
7
8
9
10
function myArrayMax(arr) {
var len = arr.length
var max = -Infinity;
while (len--) {
if (arr[len] > max) {
max = arr[len];
}
}
return max;
}

(15) forEach()

遍历数组的每一个元素,为每一个元素调用一次函数。

1
数组名.forEach(函数)

(16) map()

遍历数组的每一个元素,为每一个元素调用一次函数,然后将所有函数返回的值组成一个新的数组。

1
2
3
4
5
6
var numbers1 = [45, 4, 9, 16, 25];
var numbers2 = numbers1.map(myFunction);

function myFunction(value) {
return value * 2;
}

(17) filter()

遍历数组的每一个元素,为每一个元素调用一次函数,然后将所有函数返回值为真的元素组成一个新的数组。

1
2
3
4
5
6
var numbers = [45, 4, 9, 16, 25];
var over18 = numbers.filter(myFunction);

function myFunction(value) {
return value > 18;
}

(18) reduce() 和 reduceRight()

用于遍历数组,从左往右或从右往左,进行累加或累减。

(19) every()

用于检查数组所有值是否达标,返回布尔值。

(20) some()

用于检查数组中是否有值达标,返回布尔值。

(21) IndexOf() 和 lastIndexOf()

在数组中从左往右或从右往左搜索元素值,返回其下标。

(22) find()

返回通过测试函数的第一个数组元素的值。

1
2
3
4
5
数组名.find(测试函数名)

function 测试函数名(value){

}

(23) findIndex()

与 find 类似,但返回的是元素的下标而非元素的值。

六、对象

1. 对象语法

1
2
3
4
5
6
7
var 对象名 = {
属性名: "属性值",
属性名: "属性值"
方法名: function(){
···
}
}

2. 对象属性

对象可以有属性。

3. 对象方法

  • 对象可以有方法

  • 方法是在对象上执行的动作

  • 方法以函数定义的形式存储

4. this

this 用于引用函数的拥有者,即拥有该函数的对象。

5. 访问对象属性

(1) 法 1

1
对象名.属性名

(2) 法 2

1
对象名["属性名"]

6. 访问对象方法

1
对象名.方法名(参数)

7. 对象对象

可以通过 new Object ,再为其添加属性和属性值:

1
2
3
4
5
var 对象名 = new Object();
对象名.属性名 = '属性值';
对象名.方法名 = function(){
···
}

6. 简洁语法

仅适用于 ES6

(1) 属性的简写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var age = 12;
var name = "Bob";
var person = {
age,
name,
}

/*
等价于:
var person = {
age: 12,
name: "Bob",
}
*/

(2) 方法的简写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var person = {
run: function(){
···
}
}

/*
等价于:
var person = {
run(){
···
}
}
*/

七、布尔

1. Boolean

用于确定表达式是否为真,返回对应的布尔值。

1
Boolean(表达式)
1
document.getElementById("demo").innerHTML = Boolean(10 > 9);

2. 布尔对象

可以通过 new 新建布尔对象。

1
2
var x = false;             
var y = new Boolean(false);

此例中, x 与 y 的值相等,但类型不相等

直接使用布尔,不要创建布尔对象。

它会拖慢执行速度,使代码复杂化,产生意想不到的结果。

八、函数

1. 声明函数的两种方式

(1) “后端”方法

1
2
3
function 函数名(参数列) {
代码;
}

(2) “前端”方法

1
2
3
var 方法变量名 = function(参数列){
代码;
}

2. 函数调用

(1) 调用形式

函数中的代码将在其他代码调用该函数时执行:

  • 当事件发生时(当用户点击按钮时)
  • 当 JavaScript 代码调用时
  • 自动的(自调用)

(2) 不加括号调用

  • 如果加括号,则函数会根据参数执行

    1
    fun()
  • 如果不加括号,则会访问函数本身

    1
    fun

    (3) 自调用函数

普通调用:

1
2
3
4
var 方法名 = function(参数列){
代码;
}
方法名(参数);
1
2
3
(function() {
代码;
})(参数);
  • 将函数用括号括起来,并在其后再增加一个括号

  • 自调用函数会在开始时自动调用自身

  • 无需为此函数命名,因为此函数无法被再次调用

3. 函数返回

JavaScript 中利用 return 返回数据,因为 JavaScript 具有动态类型这一特性,因此无需指定返回值类型。

当 JavaScript 到达 return 语句时,函数将停止执行。

4. 函数是对象

(1) typeof

用 typeof() 将会返回 function

(2) 属性和方法

① length
1
函数名.length

返回函数被调用时收到的参数数目。

② toString
1
函数名.toString()

将函数返回值以字符串形式返回。

5. 函数参数

  • JavaScript 不会对参数值进行任何检查,包括数据类型、数量。

  • 如果调用时值给少了,则未被赋值的参数将被设置为 undefined

  • 如果调用时值过多,则默认会自动截取足够的值

    • 普通参数传递是值传递,因此在函数内对参数的改变并不会反馈到函数外
    • 对象传递是引用传递,因此在函数中对对象的改变将会反馈到函数之外

6. arguments

每一个函数内部都有内置对象 arguments 。

可以简单把它理解成:在每个函数内部都有一个 arguments 数组,它由调用函数时传入的形参组成,因此可以用 arguments 来处理所有参数,而无需担心传值过多

7. call

call 的作用是,调用对象的属性作为函数的参数。

1
2
3
4
5
6
7
8
9
10
var person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
var person1 = {
firstName:"Bill",
lastName: "Gates",
}
person.fullName.call(person1); // 将返回 "Bill Gates"

通过 person 对象调用函数 fullName ,并用 call(person1) 调用 person1 的对象属性,作为参数传入函数中。

call() 方法可以带有参数,即对象的属性和参数一起传入函数中。

8. apply

和 call 类似,调用对象的属性作为函数的参数,但 apply 只能拥有两个参数,对象和数组,而 call 可以传入任意数量的参数。

由于数组没有 max 方法,因此可以调用 Math.max ,并传入空对象和数组来实现这一操作。

1
Math.max.apply(null, 数组)

九、局部变量与全局变量

1. 局部变量

在函数中定义的变量,会成为函数的局部变量,它只能在函数内访问。

2. 全局变量

  • 在函数外声明的变量是全局变量

  • 在函数内为尚未声明的变量赋值,该变量为全局变量

    1
    2
    3
    4
    5
    function 方法名() {
    var 变量名 = 值; // 定义了一个局部变量

    变量名 = 值; // 定义了一个全局变量
    }

十、事件

1. 直接向元素分配事件

JavaScript 允许在事件发生时执行代码,通过下面的语句添加事件处理程序:

1
<元素名 事件名="代码">

1
<元素名 事件名='代码'>

例如:

1
<button onclick="myFunction()">点击调用函数</button>

2. 通过 DOM 分配事件

1
2
3
<script>
document.getElementById(元素id).onclick = function(){函数名()};
</script>

这种做法可以更好地将 HTML 和 JavaScript 分离。

3. 常见事件

事件 描述
onchange HTML 元素已被改变
onclick 用户点击了 HTML 元素
onmouseover 用户把鼠标移动到 HTML 元素上
onmouseout 用户把鼠标移开 HTML 元素
onkeydown 用户按下键盘按键
onload 浏览器已经完成页面加载

十一、严格模式

1. 声明严格模式

1
"use strict";

请在 JavaScript 代码中的最开头声明严格模式。

2. 严格模式

  • 不允许为尚未声明的变量赋值
  • 不允许删除变量或对象
  • 不允许删除函数
  • 不允许重复的参数名
  • 不允许八进制数值
  • 不允许转义字符
  • 不允许向只读属性写入
  • 预留了许多关键字,不允许使用

参考