Loading

[03] JS-基础语法(二)

1. 判断、循环

1.1 if-else

  • if 语句
  • if else 语句
  • if else if else 语句

e.g. 编写一个程序,获取一个用户输入的整数,然后显示这个数是奇数还是偶数。

// 编写一个程序,获取一个用户输入的整数
// let num = +prompt("请输入一个整数")
let num = parseInt(prompt("请输入一个整数"))

// 验证一下,用户的输入是否合法,只有是有效数字时,我们才检查它是否是偶数
if (isNaN(num)) {
  alert("你的输入有问题,请输入整数!")
} else {
  // 我们不能使用 == 或 === 来检查一个值是否是NaN,要使用isNaN()函数来检查一个值是否是NaN
  // num % 1 !== 0 说明是浮点数
  if (isNaN(num) || num % 1 !== 0) {
    alert(`${num} 是偶数!`)
  } else {
    alert(`${num} 是奇数!`)
  }
}

1.2 switch-case

语法格式如下:

switch (表达式){
    case value1:
        statements1  // 当表达式的结果等于 value1 时,则执行该代码
        break;
    case value2:
        statements2  // 当表达式的结果等于 value2 时,则执行该代码
        break;
    ...
    case valueN:
        statementsN  // 当表达式的结果等于 valueN 时,则执行该代码
        break;
    default :
        statements   // 如果没有与表达式相同的值,则执行该代码
}
  • switch 语句是逐行执行的,当 switch 语句找到一个与之匹配的 case 子句时(全等比较),不仅会执行该子句对应的代码,还会继续向后执行,直至 switch 语句结束。为了防止这种情况产生,需要在每个 case 子句的末尾使用 break 来跳出 switch 语句。break 除了可以用来跳出 switch 语句外,还可以用来跳出循环语句(for、for in、while、do while 等)。
  • case 子句可以省略语句,这样当匹配时,不管下一个 case 条件是否满足,都会继续执行下一个 case 子句的语句。
  • 在 switch 语句中,case 子句只是指明了执行起点,但是没有指明执行的终点,如果在 case 子句中没有 break 语句,就会发生连续执行的情况,从而忽略后面 case 子句的条件限制,这样就容易破坏 switch 结构的逻辑。
  • 如果在函数中使用 switch 语句,可以使用 return 语句终止 switch 语句,防止代码继续执行。
  • default 是 switch 子句,可以位于 switch 内任意位置,不会影响其它 case 子句的正常执行。下面结合示例介绍使用 default 语句应该注意 3 个问题。

【例一】

var id = 1;
switch (id) {
  default : 
    console.log("游客");
    break;
  case 1 : 
    console.log("普通会员");
    break;
  case 2 :
    console.log("VIP会员");
    break;
  case 3 :
    console.log("管理员");
    break;
}
// ----------
// 普通会员
// ----------

【例二】在下面代码中,JS 先检测 case 表达式的值,由于 case 表达式的值都不匹配,则跳转到 default 子句执行,然后继续执行 case 1 和 case 2 子句。但是,最后不会返回 default 子句再重复执行。

id = 3;
switch (id) {
  default : 
    console.log("游客");
  case 1 :
    console.log("普通会员");
  case 2 :
    console.log("VIP会员");
}
// ----------
// 游客
// 普通会员
// VIP会员
// ----------

default 语句与 case 语句简单比较如下:

  • 语义不同:default 为默认项,case 为判例。
  • 功能扩展:default 选项是唯一的,不可以扩展。而 case 选项是可扩展的,没有限制。
  • 异常处理:default 与 case 扮演的角色不同,case 用于枚举,default 用于异常处理。

1.3 while

while (条件表达式) {
  // 要执行的代码
}

do {
  // 需要执行的代码
} while (条件表达式);

1.4 for

(1)for 循环适合在已知循环次数时使用

for(initialization; condition; increment) {
  // 要执行的代码
}

for 循环中括号中的三个表达式是可以省略的,但是用于分隔三个表达式的分号不能省略。

(2)for-in 循环是一种特殊类型的循环,也是普通 for 循环的变体,主要用来遍历对象,使用它可以将对象中的属性依次循环出来。

for (variable in object) {
  // 要执行的代码
}

其中,variable 为一个变量,每次循环时这个变量都会被赋予不同的值,我们可以在 {} 中使用这个变量来进行一系列操作;object 为要遍历的对象,在每次循环中,会将 object 对象中的一个属性的键赋值给变量 variable,直到对象中的所有属性都遍历完。

(3)for-of 是 ECMAScript6 中新添加的一个循环方式,与 for-in 循环类似,也是普通 for 循环的一种变体。使用 for-of 循环可以轻松的遍历数组或者其它可遍历的对象,例如字符串、对象等。

for (variable of iterable) {
  // 要执行的代码
}

其中,variable 为一个变量,每次循环时这个变量都会被赋予不同的值,我们可以在后面的 {} 中使用这个变量来进行一系列操作;iterable 为要遍历的内容,在每次循环中,会将 iterable 中的一个值赋值给变量 variable,直到 iterable 中的所有值都遍历完。

2. 跳出循环

2.1 break

使用 break 语句可以跳出 switch 语句。其实使用 break 语句还可以用来跳出循环,让程序继续执行循环之后的代码(如果有的话)。

2.2 continue

continue 语句用来跳过本次循环,执行下次循环。当遇到 continue 语句时,程序会立即重新检测条件表达式,如果表达式结果为真则开始下次循环,如果表达式结果为假则退出循环。

break 语句用来跳出整个循环,执行循环后面的代码;continue 语句用来跳过当次循环,继续执行下次循环。

2.3 JS 标签

从 JavaScript 1.2 开始,可以将标签与 break 和 continue 结合使用,来更精确的控制程序的执行。

JavaScript 中的标签与 HTML 中的标签不同,JavaScript 中的标签就是一个标识符(类似变量名),后面跟随一个冒号:。JavaScript 标签可以声明在任何语句或者代码块之前,并与 break 或 continue 配合来跳出特定的循环,例如当多个循环嵌套使用时,单纯使用 break 只能跳出当前的循环,无法跳出外层循环,如果将 break 与标签配合使用,则可以一次跳出多层循环。

outerloop:                          // 定义一个标签    
for (var i = 0; i < 5; i++) {
   document.write("外层循环: " + i + "<br />");
   innerloop:                       // 定义一个标签
   for (var j = 0; j < 5; j++) {
      if (j > 3 ) break ;           // 跳出内层循环
      if (i == 2) break innerloop;  // 跳出内层讯息
      if (i == 4) break outerloop;  // 跳出外层循环
      document.write("内层循环: " + j + " <br />");
   }
}

break 或 continue 与标签之间不能出现换行。另外,标签名称和相关循环之间不能出现其它代码。

3. JS 函数

函数也是一个对象,它具有其他对象所有的功能。

函数是一组执行特定任务(具有特定功能)的,可以重复使用的代码块,前面几节中用到的 alert()、write() 就是 JavaScript 中内置的函数。

除了使用内置函数外,我们也可以自行创建函数(自定义函数),然后在需要的地方调用这个函数,这样不仅可以避免编写重复的代码,还有利于代码的后期维护。本节我们主要来介绍一下如何使用 JavaScript 编写一个自己的函数。

3.1 定义函数

JS 函数声明需要以 function 关键字开头,之后为要创建的函数名称,function 关键字与函数名称之间使用空格分开,函数名之后为一个括号 (),括号中用来定义函数中要使用的参数(多个参数之间使用逗号 , 分隔开),一个函数最多可以有 255 个参数,最后为一个花括号 {},花括号中用来定义函数的函数体(即实现函数的代码),如下所示:

// 1.函数声明
function 函数名() {
  // 语句...
}

// 2.函数表达式
const 变量 = function() {
  // 语句...
}

// 3.箭头函数
() => {
  // 语句...
}

示例代码如下:

function fn(){
  console.log("函数声明所定义的函数")
}

const fn2 = function() {
  console.log("函数表达式")
}

const fn3 = () => {
  console.log("箭头函数")
}

上面示例中定义了一个函数 sayHello(),该函数需要接收一个参数 name,调用该函数会在页面中输出“Hello! ...”。

3.2 参数说明

JS 中不会检查参数的类型,可以传递任何类型的值作为参数。

形式参数
  - 在定义函数时,可以在函数中指定数量不等的形式参数(形参)
  - 在函数中定义形参,就相当于在函数内部声明了对应的变量但是没有赋值

实际参数
  - 在调用函数时,可以在函数的()传递数量不等的实参
  - 实参会赋值给其对应的形参
  - 参数:
    1.如果实参和形参数量相同,则对应的实参赋值给对应的形参
    2.如果实参多于形参,则多余的实参不会使用
    3.如果形参多于实参,则多余的形参为undefined

在 JS 中,函数也是一个对象(一等函数),别的对象能做的事情,函数也可以。所以函数也可以作为参数传递。

【参数的默认值】在定义函数时,您可以为函数的参数设置一个默认值,这样当我们在调用这个函数时,如果没有提供参数,就会使用这个默认值作为参数值,如下例所示:

// 定义参数时,可以为参数指定默认值。
function sayHello(name = "World"){
  document.write("Hello " + name);
}
sayHello();           // 输出:Hello World
sayHello('TREE');     // 输出:Hello TREE

// 当箭头函数中只有一个参数时,可以省略()
const fn2 = a => {
  console.log("a =", a);
}

3.3 调用函数

一旦定义好了一个函数,我们就可以在当前文档的任意位置来调用它。调用函数非常简单,只需要函数名后面加上一个括号即可,例如 alert()、write()。注意,如果在定义函数时函数名后面的括号中指定了参数,那么在调用函数时也需要在括号中提供对应的参数。

function sayHello(name){
    document.write("Hello " + name);
}
// 调用 sayHello() 函数
sayHello('TREE6x7');

JavaScript 对于大小写敏感,所以在定义函数时 function 关键字一定要使用小写,而且调用函数时必须使用与声明时相同的大小写来调用函数。

3.4 函数返回值

在函数中可以使用 return 语句将一个值(函数的运行结果)返回给调用函数的程序,这个值可以是任何类型,例如数组、对象、字符串等。对于有返回值的函数,我们可以会使用一个变量来接收这个函数的返回值,示例代码如下:

function getSum(num1, num2){
    return num1 + num2;
}

var sum1 = getSum(7, 12);      // 函数返回值为:19
var sum2 = getSum(-5, 33);     // 函数返回值为:28

return 语句通常在函数的末尾定义,当函数运行到 return 语句时会立即停止运行,并返回到调用函数的地方继续执行。

另外,一个函数只能有一个返回值,若要返回多个值则,则可以将值放入一个数组中,然后返回这个数组即可,如下例所示:

function division(dividend, divisor){
    var quotient = dividend / divisor;
    var arr = [dividend, divisor, quotient]
    return arr;
}

var res = division(100, 4)
document.write(res[0]);         // 输出:100
document.write(res[1]);         // 输出:4
document.write(res[2]);         // 输出:25

任何值都可以作为返回值使用(包括对象和函数之类),如果 return 后不跟任何值,则相当于返回 undefined;如果不写 return,那么函数的返回值依然是 undefined。

箭头函数的返回值可以直接写在箭头后,如果直接在箭头后设置对象字面量为返回值时,对象字面量必须使用 () 括起来。

const sum = (a, b) => a + b
let result = sum(123, 456)

const fn = () => ({name:"孙悟空"})
result = fn()
console.log(result)

3.5 函数表达式

函数表达式与声明变量非常相似,是另外一种声明函数的形式,语法格式如下:

var myfunction = function name(parameter_list){
  // 函数中的代码
};

参数说明如下:

  • myfunction:变量名,可以通过它来调用等号之后的函数;
  • name:函数名,可以省略(一般情况下我们也会将其省略),如果省略那么该函数就会成为一个匿名函数;
  • parameter_list:为参数列表,一个函数最多可以有 255 个参数。

示例代码如下(在函数声明中,不需要在右花括号后放置分号,但若使用函数表达式就应该在表达式的最后以分号结尾):

// 函数声明
function getSum(num1, num2) {
  var total = num1 + num2;
  return total;
}

// 函数表达式
const getSum = function(num1, num2) {
  var total = num1 + num2;
  return total;
};

上面示例中的两个函数是等价的,它们的功能、返回值、调用方法都是相同的。

函数声明和函数表达式虽然看起来非常相似,但它们的运行方式是不同的,如下例所示:

declaration();          // 输出: function declaration
function declaration() {
    document.write("function declaration");
}

expression();           // 报错:Uncaught TypeError: undefined is not a function
var expression = function() {
    document.write("function expression");
};

如上例所示,如果函数表达式在定义之前被调用,会抛出异常(报错),但函数声明则可以成功运行。这是因为在程序执行前,JavaScript 会先对函数声明进行解析,因此无论是在函数声明前还是声明后调用函数都是可行的。而函数表达式则是将一个匿名函数赋值给一个变量,所以在程序还没有执行到该表达式之前,相当于函数还未定义,因此无法调用。

4. 事件处理

JS 事件(event)是当用户与网页进行交互时发生的事情,例如单机某个链接或按钮、在文本框中输入文本、按下键盘上的某个按键、移动鼠标等等。当事件发生时,您可以使用 JavaScript 中的事件处理程序(也可称为事件监听器)来检测并执行某些特定的程序。

一般情况下事件的名称都是以单词 on 开头的,例如点击事件 onclick、页面加载事件 onload 等。下表中列举了一些 JavaScript 中常用的事件:

4.1 事件绑定

事件只有与 HTML 元素绑定之后才能被触发,为 HTML 元素绑定事件处理程序的方法由很多,最简单的就是通过 HTML 事件属性来直接绑定事件处理程序,例如 onclick、onmouseover、onmouseout 等属性。

以 onclick 属性为例,通过该属性我们可以为指定的 HTML 元素定义鼠标点击事件(即在该元素上单击鼠标左键时触发的事件),示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript</title>
</head>
<body>
    <button type="button" onclick="myBtn()">按钮</button>
    <script type="text/javascript">
        function myBtn(){
          alert("Hello World!");
        }
    </script>
</body>
</html>

除了上述方法外,我们也可以直接使用 JavaScript 中提供的内置函数来为指定元素绑定事件处理程序,如下例所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript</title>
</head>
<body>
    <button type="button" id="myBtn">按钮</button>
    <script>
        function sayHello() {
          alert('Hello World!');
        }
        document.getElementById("myBtn").onclick = sayHello;
    </script>
</body>
</html>

4.2 事件示例

一般情况下,事件可以分为 4 大类 —— 鼠标事件、键盘事件、表单事件和窗口事件,另外还有一些其它事件。下面通过几个示例来简单介绍一些比较常用的事件。

(1)onmouseover 事件

onmouseover 事件就是指当用户鼠标指针移动到元素上时触发的事件,示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript</title>
</head>
<body>
    <button type="button" onmouseover="alert('您的鼠标已经移动到了该按钮上');">请将鼠标移动至此处</button><br>
    <a href="#" onmouseover="myEvent()">请将鼠标移动至此处</a>
    <script>
        function myEvent() {
          alert('您的鼠标已经移动到了该链接上');
        }
    </script>
</body>
</html>

(2)onmouseout 事件

onmouseout 事件与 onmouseover 事件正好相反,onmouseout 事件会在鼠标从元素上离开时触发,示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript</title>
</head>
<body>
    <div style="width: 350px; height: 200px; border:1px solid black" id="myBox"></div>
    <script>
        function myEvent() {
          alert('您的鼠标已经离开指定元素');
        }
        document.getElementById("myBox").onmouseout = myEvent;
    </script>
</body>
</html>

(3)onkeydown 事件

onkeydown 事件是指当用户按下键盘上的某个按键时触发的事件,示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript</title>
</head>
<body>
    <input type="text" onkeydown="myEvent()">
    <script>
        function myEvent() {
          alert("您按下了键盘上的某个按钮");
        }
    </script>
</body>
</html>

(4)onkeyup 事件

onkeyup 事件是指当用户按下键盘上的某个按键并将其释放(即按下并松开某个按键)时触发的事件,示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript</title>
</head>
<body>
    <input type="text" onkeyup="myEvent()">
    <script>
        function myEvent() {
          alert("您按下了键盘上的某个按钮,并将其释放了");
        }
    </script>
</body>
</html>

5. 作用域

在 JavaScript 中,您可以在任意位置声明变量,但不同的位置会影响变量的可用范围,这个范围称为作用域。作用域可以大致分为两种类型,分别是全局作用域和局部作用域。下面就来分别介绍一下。

5.1 全局作用域

全局作用域是指变量可以在当前脚本的任意位置访问,拥有全局作用域的变量也被称为“全局变量”,一般情况下拥有以下特征的变量具有全局作用域:

  • 最外层的函数和在最外层函数外面定义的变量拥有全局作用域;
  • 所有未定义直接赋值的变量拥有全局作用域;
  • 全局作用域中的变量是全局变量,可以在任意位置访问;
  • 所有 window 对象的属性拥有全局作用域,例如 window.name、window.location、window.top 等。

示例代码如下:

var str = "Hello World!";

function myFun(){
    document.write(str);    // 输出:Hello World!
}

myFun();

document.write(str);        // 输出:Hello World!

实际情况下,所有具有全局作用域的变量都会被绑定到 window 对象中,成为 window 对象的一个属性,如下例所示:

var str = "JavaScript";
document.write(str);                    // 输出:JavaScript
document.write(window.str);             // 输出:JavaScript
document.write(str === window.str);     // 输出:true

5.2 局部作用域

  • 块作用域

    • 块作用域是一种局部作用域;

    • 块作用域在代码块执行时创建,代码块执行完毕它就销毁;

    • 在块作用域中声明的变量是局部变量,只能在块内部访问,外部无法访问。

  • 函数作用域

    • 函数作用域也是一种局部作用域;
    • 函数作用域在函数调用时产生,调用结束后销毁;
    • 函数每次调用都会产生一个全新的函数作用域;
    • 在函数中定义的变量是局部变量,只能在函数内部访问,外部无法访问。

示例代码 1:

let a = "变量a"

{
  let b = "变量b"

  {
    {
      console.log(b)
    }
  }
}

{
  console.log(b)
}

示例代码 2:

function myFun(){
    var str = "Hello World!";
    document.write(str);    // 输出:Hello World!
}

document.write(str);        // 报错:str is not defined

在函数内定义的局部变量只有在函数被调用时才会生成,当函数执行完毕后会被立即销毁。

5.3 作用域链

当我们使用一个变量时,JS 解释器会优先在当前作用域中寻找变量,如果找到了则直接使用。如果没找到,则去上一层作用域中寻找,找到了则使用,还没找到则继续去上一层寻找,以此类推。如果一直到全局作用域都没找到,则报错 xxx is not defined。

6. 补充说明

6.1 变量/函数·提升

  • 【变量的提升】使用 var 声明的变量,它会在所有代码执行前被声明,所以我们可以在变量声明前就访问变量。let 声明的变量实际也会提升,但是在赋值之前解释器禁止对该变量的访问。

  • 【函数的提升】使用函数声明创建的函数,会在其他代码执行前被创建,所以我们可以在函数声明前调用函数。

6.2 立即执行函数

希望可以创建一个只执行一次的匿名函数 => 立即执行函数(IIFE)

立即是一个匿名的函数,并它只会调用一次。可以利用 IIFE 来创建一个一次性的函数作用域,避免变量冲突的问题。

(function(){
  let a = 10
  console.log(111)
}());
posted @ 2024-04-18 20:29  tree6x7  阅读(4)  评论(0编辑  收藏  举报