1.前提

Html是一种标记语言用来结构化我们网页内容并赋予内容含义,例如定义段落标题数据表,或在页面嵌入图片视频

Css是一种样式规则语言,可将样式应用于 HTML 内容例如设置背景颜色字体,在多个列中布局内容

JavaScript 是一种脚本语言可以用来创建动态更新内容控制多媒体制作图像动画,还有很多

2.简介

JavaScript 是一种轻量级编程语言

JavaScript 是可插入 HTML 页面编程代码

JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行

3.JavaScrip用法

HTML 中的 Javascript 脚本代码必须位于 <script&gt; 与 </script&gt; 标签之间

Javascript 脚本代码可被放置在 HTML 页面的 <body&gt; 和 <head&gt; 部分

3.1<script><script/> 标签

如需在 HTML 页面中插入 JavaScript,请使用 <script> 标签

<script> 和 </script> 会告诉 JavaScript 在何处开始和结束

<script> 和 </script> 之间的代码包含了 JavaScript

<script>
        alert(“我的第一个 JavaScript”);
</script>

您无需理解上面的代码。只需明白,浏览器解释执行位于 <script> 和 </script>之间的 JavaScript 代码

那些老旧的实例可能会在 <script> 标签使用 type=”text/javascript“。现在已经不必这样做了。JavaScript 是所有现代浏览器以及 HTML5 中的默认脚本语言

3.2 <body> 中的 JavaScript

JavaScript 会在页面加载时向 HTML 的 <body> 写文本

<!DOCTYPE html>
<html>
<body>
.
.
<script>
document.write(“<h1>这是一个标题</h1>”);
document.write(“<p>这是一个段落</p>”);
</script>
.
.
</body>
</html>

3.3<head> 中的 JavaScript 函数

函数会在点击按钮时被调用

<!DOCTYPE html>
<html>
<head>
<script>
   function myFunction()
     {
              document.getElementById(“demo“).innerHTML=”我的第一个 JavaScript 函数“;
          }
</script>
</head>
<body>
       <h1>我的 Web 页面</h1>
       <p id=”demo“>一个段落</p>
       <button type=”button” οnclick=”myFunction()”>尝试一下</button>
</body>
</html>

3.4外部的 JavaScript

可以脚本保存外部文件中。外部文件通常包含多个网页使用代码

如需使用外部文件,请在 <script> 标签的 “src属性设置该 .js 文件

<!DOCTYPE html>
<html>
<body>
        <script src=”myScript.js”></script>
</body>
</html>

myScript.js 文件代码如下

function myFunction()
{
    document.getElementById(“demo“).innerHTML=”我的第一个 JavaScript 函数”;
}

 

4.Chrome 浏览器执行 JavaScript

如何在 Chrome 浏览器上进行 JavaScript 代码的运行调试

我们在 Chrome 浏览器可以通过按下 F12 按钮或者右击页面,选择检查开启开发者工具

可以在右上角菜单栏选择 “更多工具“=》”开发者工具” 来开启

4.1Console 窗口调试 JavaScript 代码

打开开发者工具后,我们可以在 Console 窗口调试 JavaScript代码,如下图

038a2bb992d544f7940eadb36f391866.png

上图中我们在 > 符号输入我们要执行的代码 console.log(“runoob”),按回车执行

我们也可以在其他地方复制一段代码过来执行比如复制以下代码到 Console 窗口,按回车执行

4.2清空 Console 窗口内容可以按以下按钮

09766048d1d54a588ff76f9816fa14cc.png

4.3Chrome snippets脚本

我们也可以在 Chrome 浏览器创建一个脚本来执行,在开发者工具中点击 Sources 面板选择 Snippets 选项卡,在导航器中右击鼠标然后选择 Create new snippet 来新建一个本文

bab35e9169994fa193eb45f7a1fa1aa0.png

如果你没看到 Snippets可以点下面板上到 >> 就能看到

点击 Create new snippet 后,会自动创建一个文件,你只需在右侧窗口输入以下代码,然后按 Command+S(Mac)或 Ctrl+S(Windows 和 Linux保存更改即可

713a5cbdb8b945349f16329d459f55ab.png

5.JavaScript 输出

JavaScript 可以通过不同方式输出数据

<p id=”demo“>我的第一个段落</p>

<script>
document.getElementById(“demo“).innerHTML = “段落已修改。”;
</script>

<script> document.write(Date());</script>

<button οnclick=”myFunction()”>点我</button>

<script>
function myFunction() {
    document.write(Date());
}
</script>

<script>
a = 5;
b = 6;
c = a + b;
console.log(c);
</script>

6.JavaScript 语法

JavaScript 代码

document.getElementById(“demo“).innerHTML=”你好 Dolly”;

JavaScript 代码块

function myFunction()
{
    document.getElementById(“demo“).innerHTML=”你好Dolly”;
}

JavaScript 语句标识符

9e04a07b512849a1b943fc82d96b5241.png

空格

JavaScript 会忽略多余的空格 您可以向脚本添加空格,来提高其可读性

7.JavaScript 注释

单行注释以 // 开头

多行注释以 /* 开始,以 */ 结尾

8.JavaScript 变量

声明(创建) JavaScript 变量

在 JavaScript 中创建变量通常称为”声明“变量

我们使用 var 关键词来声明变量

var carname;

变量声明之后,该变量是空的(它没有值)

如需向变量赋值,请使用等号:

carname=”Volvo“;

不过,您也可以在声明变量时对其赋值

var carname=”Volvo“;

在下面的例子中,我们创建了名为 carname 的变量,并向其赋值 “Volvo“,然后把它放入 id=”demo” 的 HTML 段落中:

var carname=”Volvo“;
document.getElementById(“demo“).innerHTML=carname;

一条语句多个变量

您可以在一条语句中声明很多变量。该语句var 开头,并使用逗号分隔变量即可

var lastname=”Doe”, age=30, job=”carpenter”;

声明也可横跨多行

var lastname=”Doe”,
age=30,
job=”carpenter”;

一条语句中声明的多个变量不可以同时赋同一个值:

var x,y,z=1;

x,y 为 undefined, z 为 1

9.JavaScript 数据类型

类型(基本类型)

字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol

注:Symbol 是 ES6 引入了一种新的原始数据类型表示独一无二的值

引用数据类型对象类型

对象(Object)、数组(Array)、函数(Function),两个特殊对象正则(RegExp)和日期(Date)

JavaScript 拥有动态类型

JavaScript 拥有动态类型。这意味着相同的变量可用作不同类型

var x;               // xundefinedvar

x = 5;                   // 现在 x数字
var x = “John”;      // 现在 x 为字符串

变量的数据类型可以使用 typeof 操作符查看

typeof “John”                // 返回 string
typeof 3.14                  // 返回 number
typeof false                 // 返回 boolean
typeof [1,2,3,4]             // 返回 object
typeof {name:’John’, age:34} // 返回 object

JavaScript 数字

JavaScript 只有一种数字类型数字可以带小数点,也可以不带

var x1=34.00;      //使用小数点来写
var x2=34;         //不使用小数点来写

JavaScript 布尔

布尔(逻辑)只能有两个值:truefalse

var x=true;
var y=false;

JavaScript 数组

下面的代码创建名为 cars数组

var cars=new Array();
cars[0]=”Saab“;
cars[1]=”Volvo“;
cars[2]=”BMW”;

var cars=new Array(“Saab“,”Volvo“,”BMW”);

 

var cars=[“Saab“,”Volvo“,”BMW”];

JavaScript 对象

对象由花括号分隔。在括号内部对象属性名称和值对的形式 (name : value) 来定义属性逗号分隔

var person={firstname:”John”, lastname:”Doe”, id:5566};

name=person.lastname;
name=person[“lastname”];

undefined 和 Null

Undefined 这个表示变量不含有值。

可以通过将变量的值设置为 null清空变量

cars=null;
person=null;

var person={firstname:”John”, lastname:”Doe”, id:5566};

// name=person.lastname;

// name=person[“lastname”];

 

var cars=[“Saab“,”Volvo“,”BMW”];

cars=null;

person=null;

console.info(cars)

声明变量类型

当您声明新变量时,可以使用关键词 “new” 来声明其类型

var carname=new String;
var x=      new Number;
var y=      new Boolean;
var cars=   new Array;
var person= new Object;

对象方法

<p id=”demo”></p>
<script>
var person = {
    firstName: “John”,
    lastName : “Doe”,
    id : 5566,

    fullName : function() 
    {
       return this.firstName + ” ” + this.lastName;
    }
};

document.getElementById(“demo”).innerHTML = person.fullName(); //调用对象方法
</script>

JavaScript 函数

函数是由事件驱动的或者当它被调用执行的可重复使用的代码块

<script> function myFunction() {

        alert(“Hello World!”);

} </script>  

 

<button οnclick=”myFunction()”>点我</button>

JavaScript 函数语法

函数就是包裹在花括号中的代码块,前面使用了关键词 function

functiofunctionname()
{
    // 执行代码
}

调用参数的函数

调用函数时,您可以向其传递值,这些值被称为参数

这些参数可以在函数中使用。

您可以发送任意多的参数,由逗号 (,) 分隔

<p>点击这个按钮,来调用参数的函数。</p>

<button οnclick=”myFunction(‘Harry Potter’,’Wizard’)”>点击这里</button>

<script>

function myFunction(name,job){

        alert(“Welcome ” + name + “, the ” + job);

}

</script>

带有返回值的函数

有时,我们会希望函数将值返回调用它的地方。

通过使用 return 语句就可以实现

在使用 return 语句时,函数会停止执行,并返回指定的值

function myFunction()
{
    var x=5;
    return x;
}

var myVar=myFunction();

function myFunction(a,b) { return a*b; } document.getElementById(“demo”).innerHTML=myFunction(4,3);

10.JavaScript 作用域

11.JavaScript 事件

HTML 事件是发生在 HTML 元素上的事情

当在 HTML 页面中使用 JavaScript 时, JavaScript 可以触发这些事件

HTML 事件可以是浏览行为,也可以是用户行为

以下是 HTML 事件实例

通常,当事件发生时,你可以做些事情。

事件触发时 JavaScript 可以执行一些代码。

HTML 元素中可以添加事件属性,使用 JavaScript 代码来添加 HTML 元素

 

在以下实例中,按钮元素添加onclick 属性 (并加上代码)

<button οnclick=”getElementById(‘demo’).innerHTML=Date()”>现在的时间是?</button>

或者

<p>点击按钮执行 <em>displayDate()</em> 函数.</p>
<button οnclick=”displayDate()”>点这里</button>
<script>
        function displayDate(){
               document.getElementById(“demo”).innerHTML=Date();
        }
</script>
        <p id=”demo”></p>

</body>

其它事件

bc43403aa96f4d02849c1fdfbe7e7366.png

12.JavaScript 字符串

JavaScript 字符串用于存储处理文本

var carname = “Volvo XC60″;

var character = carname[7];

const name = “RUNOOB”;
let letter = name[2];

document.getElementById(“demo”).innerHTML = letter;

字符串长度

可以使用内置属性 length 来计算字符串长度

var txt = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”;

var sln = txt.length;

13.JavaScript 运算符

比较逻辑运算用于测试 true 或者 false

比较运算符

8b083f780d9741c78c260495d839bf52.png

逻辑运算

5d0c417af15c415496b497d4c31e02ae.png

 

14.JavaScript if…Else 语句

通常在写代码时,您总是需要不同的决定来执行不同动作。您可以在代码中使用条件语句来完成该任务

在 JavaScript 中,我们可使用以下条件语句:

  • if 语句 – 只有当指定条件为 true 时,使用该语句来执行代码
  • if…else 语句 – 当条件为 true 时执行代码,当条件为 false 时执行其他代码
  • if…else if….else 语句– 使用该语句来选择多个代码块之一来执行
  • switch 语句 – 使用该语句来选择多个代码块之一来执行

15.JavaScript switch 语句

switch(n)
{
    case 1:
        执行代码块 1
        break;
    case 2:
        执行代码块 2
        break;
    default:
        与 case 1 和 case 2 不同时执行的代码
}

16.JavaScript for 循环

for 循环

for (var i=0; i<5; i++)
{
      x=x + “该数字为 ” 
}

For/In 循环

JavaScript for/in 语句循环遍历对象的属性

var person={fname:”Bill”,lname:”Gates“,age:56}; 
 
for (x in person)  // x 为属性名
{
    txt=txt + person[x];
}

while 循环

while (i<5)
{
    x=x + “The number is ” + i + “<br>”;
    i++;
}

17.JavaScript breakcontinue 语句

break 语句用于跳出循环

continue 用于跳过循环中的一个迭代

for (i=0;i<10;i++){
    if (i==3){
        break;
    }
    x=x + “The number is ” + i + “<br>”;
}

for (i=0;i<=10;i++){

        if (i==3) continue;

               console.info(i)

}

18.JavaScript typeof, null, 和 undefined

typeof 操作符检测变量的数据类型

typeof “John”                // 返回 string 
typeof 3.14                  // 返回 number
typeof false                 // 返回 boolean
typeof [1,2,3,4]             // 返回 object
typeof {name:’John’, age:34} // 返回 object

null

在 JavaScript 中 null 表示什么没有“。

null是一个只有一个值的特殊类型。表示一个空对象引用

var  person = null;           // 值为 null(空), 但类型为对象

var  person = undefined;     // 值为 undefined, 类型为 undefined

undefined

在 JavaScript 中, undefined 是一个没有设置值的变量

var person;  // 值为 undefined(空), 类型是undefined

19.JavaScript 正则表达式

20.JavaScript 表单验证

HTML 表单验证可以通过 JavaScript 来完成

以下实例代码用于判断表单字段(fname)值是否存在, 如果不存在,就弹出信息,阻止表单提交

function validateForm() {
    var x = document.forms[“myForm“][“fname”].value;
    if (x == null || x == “”) {
        alert(“需要输入名字。”);
        return false;
    }
}

<form name=”myFormaction=”demo_form.php” οnsubmit=”return validateForm()” method=”post“>
名字: <input type=”text” name=”fname”>
         <input type=”submit” value=”提交“>
</form>

HTML 表单自动验证

HTML 表单验证也可以通过浏览器来自动完成

如果表单字段 (fname) 的值为空required 属性会阻止表单提交

<form action=”demo_form.phpmethod=”post“>
  <input type=”text” name=”fname” required=”required“>
  <input type=”submit” value=”提交“>
</form>

21.JavaScript this 关键字

面向对象语言this 表示当前对象的一个引用

但在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变

方法中的 this

在对象方法中, this 指向调用它所在方法的对象

在上面一个实例中,this 表示 person 对象

fullName 方法所属的对象就是 person

<script>
// 创建一个对象
var person = {
  firstName: “John”,
  lastName : “Doe”,
  id     : 5566,
  fullName : function() {
    return this.firstName + ” ” + this.lastName;
  }
};

// 显示对象的数据
document.getElementById(“demo”).innerHTML = person.fullName();
</script>

事件中的 this

在 HTML 事件句柄中,this 指向接收事件的 HTML 元素

<button οnclick=”this.style.display=’none‘”>点我后我就消失了</button>

对象方法绑定

下面实例中,this 是 person 对象,person 对象是函数的所有者

<script>
// 创建一个对象
var person = {
  firstName  : “John”,
  lastName   : “Doe”,
  id     : 5566,
  myFunction : function() {
    return this;
  }
};

// 显示表单数据
document.getElementById(“demo”).innerHTML = person.myFunction();
</script>

显式函数绑定

在 JavaScript 中函数也是对象,对象则有方法,applycall 就是函数对象的方法。这两个方法异常强大,他们允许切换函数执行的上下文环境context),即 this 绑定的对象。

在下面实例中,当我们使用 person2 作为参数调用 person1.fullName 方法时, this 将指向 person2, 即便它是 person1 的方法:

<script>
var person1 = {
  fullName: function() {
    return this.firstName + ” ” + this.lastName;
  }
}
var person2 = {
  firstName:”John”,
  lastName: “Doe”,
}
var x = person1.fullName.call(person2); 
document.getElementById(“demo”).innerHTML = x; 
</script>

22. letconst区别

ES2015(ES6) 新增加了两个重要的 JavaScript 关键字let 和 const

let 声明的变量只在 let 命令所在的代码块内有效。

const 声明一个只读常量,一旦声明,常量的值就不能改变。

在 ES6 之前,JavaScript 只有两种作用域: 全局变量 与 函数内的局部变量

全局变量

在函数外声明的变量作用域是全局的:

var carName = “Volvo“;
 
// 这里可以使用 carName 变量
 
function myFunction() {
    // 这里也可以使用 carName 变量
}

全局变量在 JavaScript 程序的任何地方都可以访问

局部变量

在函数内声明的变量作用域是局部的(函数内):

// 这里不能使用 carName 变量
 
function myFunction() {
    var carName = “Volvo”;
    // 这里可以使用 carName 变量
}
 
// 这里不能使用 carName 变量

函数内使用 var 声明的变量只能在函数内访问,如果不使用 var 则是全局变量

块级作用域(Block Scope)

使用 var 关键字声明的变量不具备块级作用域的特性,它在 {} 外依然能被访问到。

{ 
    var x = 2; 
}
// 这里可以使用 x 变量

在 ES6 之前,是没有块级作用域的概念的。

ES6 可以使用 let 关键字实现块级作用域。

let 声明的变量只在 let 命令所在的代码块 {} 内有效,在 {} 之外不能访问


    let x = 2;
}
// 这里不能使用 x 变量

重新定义变量

使用 var 关键字重新声明变量可能会带来问题

在块中重新声明变量也会重新声明块外的变量:

var x = 10;
// 这里输出 x 为 10

    var x = 2;
    // 这里输出 x 为 2
}
// 这里输出 x 为 2

let 关键字就可以解决这个问题,因为它只在 let 命令所在的代码块 {} 内有效。

var x = 10;
// 这里输出 x 为 10

    let x = 2;
    // 这里输出 x 为 2
}
// 这里输出 x 为 10

循环作用域

使用 var 关键字:

var i = 5;
for (var i = 0; i < 10; i++) {
    // 一些代码…
}
// 这里输出 i 为 10

使用 let 关键字:

var i = 5;
for (let i = 0; i < 10; i++) {
    // 一些代码…
}
// 这里输出 i 为 5

第一个实例中,使用了 var 关键字,它声明的变量是全局的,包括循环体内与循环体外。

第二个实例中,使用 let 关键字, 它声明的变量作用域只在循环体内,循环体外的变量不受影响

变量提升

JavaScript 中,函数及变量的声明都将被提升到函数的最顶部

JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明

x = 5; // 变量 x 设置为 5

elem = document.getElementById(“demo”); // 查找元素 
elem.innerHTML = x;                     
// 在元素中显示 xvar x; // 声明 x

var x = 5; // 初始化 x
var y;     // 声明 y

elem = document.getElementById(“demo”); // 查找元素
elem.innerHTML = x + ” ” + y;           // 显示 x 和 y

y = 7;    // 设置 y 为 7

const 关键字

const 用于声明一个或多个常量,声明时必须进行初始化,且初始化后值不可再修改

const PI = 3.141592653589793;
PI = 3.14;      // 报错
PI = PI + 10;   // 报错

const 的本质: const 定义的变量并非常量,并非不可变,它定义了一个常量引用一个值。

使用 const 定义的对象或者数组其实可变的。下面的代码并不会报错

// 创建常量对象
const car = {type:”Fiat”, model:”500″, color:”white”};
 
// 修改属性:
car.color = “red“;
 
// 添加属性
car.owner = “Johnson”;

// 创建常量数组
const cars = [“Saab“, “Volvo”, “BMW”];
 
// 修改元素
cars[0] = “Toyota”;
 
// 添加元素
cars.push(“Audi“);

23.JavaScript JSON

JSON 是用于存储传输数据格式

JSON 通常用于服务端网页传递数据

什么是 JSON

JSON 是一种轻量级的数据交换格式

JSON 语法规则

JSON 数据 – 一个名称对应一个值

JSON 数据格式为 键/值 对,就像 JavaScript 对象属性。

键/值对包括字段名称(在双引号中),后面一个冒号,然后是值

“name”:”Runoob”

JSON 对象

JSON 对象保存在大括号内。

就像在 JavaScript 中, 对象可以保存多个 键/值 对:

{“name”:”Runoob”, “url“:”www.runoob.com”}

JSON 数组

JSON 数组保存在中括号内。

就像在 JavaScript 中, 数组可以包含对象

sites”:[
    {“name”:”Runoob”, “url“:”www.runoob.com”}, 
    {“name”:”Google”, “url“:”www.google.com”},
    {“name”:”Taobao”, “url“:”www.taobao.com”}
]

JSON 字符串转换为 JavaScript 对象

通常我们从服务器读取 JSON 数据,并在网页显示数据

var text = ‘{ “sites” : [‘ +
‘{ “name”:”Runoob” , “url“:”www.runoob.com” },’ +
‘{ “name”:”Google” , “url“:”www.google.com” },’ +
‘{ “name”:”Taobao” , “url“:”www.taobao.com” } ]}’;

然后,使用 JavaScript 内置函数 JSON.parse() 将字符转换为 JavaScript 对象:

var obj = JSON.parse(text);

最后,在你的页面中使用新的 JavaScript 对象:

var text = ‘{ “sites” : [‘ +
    ‘{ “name”:”Runoob” , “url“:”www.runoob.com” },’ +
    ‘{ “name”:”Google” , “url“:”www.google.com” },’ +
    ‘{ “name”:”Taobao” , “url“:”www.taobao.com” } ]}’;
    
obj = JSON.parse(text);
document.getElementById(“demo”).innerHTML = obj.sites[1].name + ” ” + obj.sites[1].url;

函数 描述
JSON.parse() 用于将一个 JSON 字符转换为 JavaScript 对象。
JSON.stringify() 用于将 JavaScript 值转换为 JSON 字符串。

例子

实现从JSON字符串转换为JS对象,使用 JSON.parse() 方法

 //结果是 {a: 'Hello', b: 'World'} 一个对象
var obj = JSON.parse('{"a": "Hello", "b": "World"}');

实现从JS对象转换为JSON字符串,使用 JSON.stringify() 方法

 //结果是 ‘{“a”: “Hello“, “b”: “World”}’ 一个JSON格式的字符串

var json = JSON.stringify({a: 'Hello', b: 'World'}); 

javascript:void(0)

创建了一个超级链接,当用户点击以后不会发生任何事

<a href=”javascript:void(0)”>单击此处什么也不会发生</a>

24.异步编程

异步(Asynchronous, async)是与同步(Synchronous, sync相对概念

程序运行同步的(同步不意味着所有步骤同时运行,而是指步骤在一个控制流列中顺序执行)。而异步概念则是不保证同步的概念,也就是说,一个异步过程的执行将不再与原有的序列顺序关系

026a4a7f724d478482a51633af758318.png

回调函数

回调函数就是一个函数,它是在我们启动一个异步任务时候就告诉它:等你完成了这个任务之后要干什么。这样一来主线程几乎不用关心异步任务状态了,他自己会善始善终

setTimeout(function () {
    document.getElementById(“demo”).innerHTML=”RUNOOB!”;
}, 3000);

25.JavaScript Promise

Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂异步任务

由于 Promise 是 ES6 新增加的,所以一些旧的浏览器并不支持

构造 Promise

现在我们新建一个 Promise 对象

new Promise(function (resolve, reject) {
    // 要做的事情…
});

通过新建一个 Promise 对象好像并没有看出它怎样 “更加优雅地书写复杂的异步任务“。我们之前遇到的异步任务都是一次异步,如果需要多次调用异步函数呢?例如,如果我想分三次输出字符串,第一次间隔 1 秒,第二次间隔 4 秒,第三次间隔 3 秒

setTimeout(function () {
    console.log(“First“);
    setTimeout(function () {
        console.log(“Second”);
        setTimeout(function () {
            console.log(“Third”);
        }, 3000);
    }, 4000);
}, 1000);

这段程序实现这个功能,但是它是用 “函数瀑布” 来实现的。可想而知,在一个复杂程序当中,用 “函数瀑布实现程序无论是维护还是异常处理都是一件特别繁琐的事情,而且会让缩进格式变得非常冗赘。

现在我们用 Promise 来实现同样的功能:

new Promise(function (resolve, reject) {
    setTimeout(function () {
        console.log(“First“);
        resolve();
    }, 1000);
}).then(function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log(“Second”);
            resolve();
        }, 4000);
    });
}).then(function () {
    setTimeout(function () {
        console.log(“Third”);
    }, 3000);
});

Promise 的构造函数

Promise 构造函数是 JavaScript 中用于创建 Promise 对象的内置构造函数

Promise 构造函数接受一个函数作为参数,该函数是同步的并且会被立即执行,所以我们称之为起始函数。起始函数包含两个参数 resolve 和 reject,分别表示 Promise 成功和失败状态

起始函数执行成功时,它应该调用 resolve 函数并传递成功的结果。当起始函数执行失败时,它应该调用 reject 函数并传递失败原因

Promise 构造函数返回一个 Promise 对象,该对象具有以下几个方法:

下面是一个使用 Promise 构造函数创建 Promise 对象的例子

const promise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    if (Math.random() < 0.5) {
      resolve(‘success‘);
    } else {
      reject(‘error‘);
    }
  }, 1000);
});
 
promise.then(result => {
  console.log(result);
}).catch(error => {
  console.log(error);
});

在上面的例子中,我们使用 Promise 构造函数创建了一个 Promise 对象,并使用 setTimeout 模拟了一个异步操作。如果异步操作成功,则调用 resolve 函数并传递成功的结果;如果异步操作失败,则调用 reject 函数并传递失败原因。然后我们使用 then 方法处理 Promise 成功状态回调函数,使用 catch 方法处理 Promise 失败状态回调函数。

这段程序会直接输出 error 或 success

resolve 和 reject 都是函数,其中调用 resolve 代表一切正常,reject 是出现异常时所调用的

 

new Promise(function (resolve, reject) {
    var a = 0;
    var b = 1;
    if (b == 0) reject(“Divide zero“);
    else resolve(a / b);
}).then(function (value) {
    console.log(“a / b = ” + value);
}).catch(function (err) {
    console.log(err);
}).finally(function () {
    console.log(“End”);
});

Promise 类有 .then() .catch() 和 .finally() 三个方法,这三个方法的参数都是一个函数,.then() 可以将参数中的函数添加当前 Promise 的正常执行序列,.catch() 则是设定 Promise 的异常处理序列,.finally() 是在 Promise 执行的最后一定会执行的序列。 .then() 传入的函数会按顺序依次执行,有任何异常都会直接跳到 catch 序列

 

new Promise(function (resolve, reject) {
    console.log(1111);
    resolve(2222);
}).then(function (value) {
    console.log(value);
    return 3333;
}).then(function (value) {
    console.log(value);
    throw “An error“;
}).catch(function (err) {
    console.log(err);
});

但是请注意以下两点

  • resolve 和 reject 的作用域只有起始函数,不包括 then 以及其他序列
  • resolve 和 reject 并不能够使起始函数停止运行,别忘了 return。

Promise 函数

上述的 “计时器程序看上去比函数瀑布还要长,所以我们可以将它的核心部分写成一个 Promise 函数

function print(delay, message) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log(message);
            resolve();
        }, delay);
    });
}

print(1000, “First“).then(function () {
    return print(4000, “Second”);
}).then(function () {
    print(3000, “Third”);
});

异步函数

异步函数(async function)是 ECMAScript 2017 (ECMA-262) 标准规范,几乎被所有浏览器所支持,除了 Internet Explorer。

在 Promise 中我们编写过一个 Promise 函数

function print(delay, message) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log(message);
            resolve();
        }, delay);
    });
}

然后用不同的时间间隔输出了三行文本

print(1000, “First”).then(function () {
    return print(4000, “Second”);
}).then(function () {
    print(3000, “Third”);
});

我们可以将这段代码变得更好看

async function asyncFunc() {
    await print(1000, “First”);
    await print(4000, “Second”);
    await print(3000, “Third”);
}
asyncFunc();

异步函数 async function 中可以使用 await 指令await 指令后必须跟着一个 Promise,异步函数会在这个 Promise 运行中暂停,直到其运行结束再继续运行

 

处理异常的机制将用 try-catch 块实现

async function asyncFunc() {
    try {
        await new Promise(function (resolve, reject) {
            throw “Some error”; // 或者 reject(“Some error”)
        });
    } catch (err) {
        console.log(err);
        // 会输出 Some error
    }
}
asyncFunc();

如果 Promise 有一个正常的返回值,await 语句也会返回它

async function asyncFunc() {
    let value = await new Promise(
        function (resolve, reject) {
            resolve(“Return value”);
        }
    );
    console.log(value);
}
asyncFunc();

总结

  •  1、Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)
  •  2、Promise构造函数接收一个函数作为参数,该函数的两个参数分别是 resolve 和 reject
  •  3、一个promise对象只能改变一次状态,成功或者失败后都会返回结果数据。
  •  4、then 方法可以接收两个回调函数作为参数,第一个回调函数是Promise对象的状态改变为 resoved 是调用,第二个回调函数是 Promise 对象的状态变为 rejected 时调用。其中第二个参数可以省略
  •  5、catch 方法,该方法相当于最近的 then 方法的第二个参数,指向 reject 的回调函数,另一个作用是,在执行resolve回调函数时,如果出错抛出异常,不会停止运行,而是进入catch 方法中。

注意:catch 只捕获最近的 then 的回调函数,前面的then的执行不成功的结果,有后面 then 的 reject 回调函数执行,如果没有后续 then 回调函数执行,则会被 catch 捕获执行

var promise =new Promise(function(resolve,reject){
    //To Do 要异步执行的事情,这个异步执行的事情有可能成功执行完毕,那么Promise将是        fulfilled状态,如果执行失败则是rejected;
    //下面测试代码,人为设置为rejected状态;
    reject(“将当前构建的Promise对象的状态由pending(进行中)设置为rejected(已拒绝)”); //当然此处也可以设置为fulfilled(已完成)状态
})

promise.then(//调用第一个then()
    success=>{
        console.log(“异步执行成功,状态为:fulfilled,成功后返回的结果是:”+success);
        return(” 当前 success “);
    },
    error=>{
        console.log(“异步执行失败,状态为rejected,失败后返回的结果是:”+error);
        return(” 当前 error “);
    }
).then(
    //调用第二个then() 因为调用第一个then()方法返回的是一个新的promise对象,此对象的状态由上面的success或者error两个回调函数的执行情况决定的:
    //如果回调函数能正常执行完毕,则新的promise对象的状态为fulfilled,下面执行success2,如果回调函数无法正常执行,则promise状态为rejected;下面执行error2
    success2=>{
        console.log(“第一个then的回调函数执行成功 成功返回结果:”+success2);
        throw(” 当前 success2 “);//自定义异常抛出
    },
    error2=>{
        console.log(“第一个then的回调函数执行失败 失败返回结果:”+error2);
        return(” 当前 error2 “);
    }
).catch(err=>{
    //当success2或者error2执行报错时,catch会捕获异常;
    console.log(“捕获异常:”+err);
});

 

26.JavaScript 函数

JavaScript 函数定义

JavaScript 使用关键字 function 定义函数。

函数可以通过声明定义,也可以是一个表达式

函数声明

函数声明后不会立即执行,会在我们需要时候调用到

function myFunction(a, b) {  return a * b;}

函数表达式

var x = function (a, b) {return a * b};
var z = x(4, 3);

Function() 构造函数

在以上实例中,我们了解到函数通过关键字 function 定义。

函数同样可以通过内置的 JavaScript 函数构造器(Function())定义

var myFunction = new Function(“a”, “b”, “return a * b”);
var x = myFunction(4, 3);

实际上,你不必使用构造函数。上面实例可以写成

var myFunction = function (a, b) {return a * b};
var x = myFunction(4, 3);

箭头函数

ES6 新增了箭头函数。

箭头函数表达式语法比普通函数表达式简洁

(参数1, 参数2, …, 参数N) => { 函数声明 }

(参数1, 参数2, …, 参数N) => 表达式(单一)
// 相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }

当只有一个参数时,圆括号是可选的

(单一参数) => {函数声明}
单一参数 => {函数声明}

没有参数的函数应该写成一对圆括号

() => {函数声明}

// ES5
var x = function(x, y) {
     return x * y;
}
 
// ES6
const x = (x, y) => x * y;

有的箭头函数都没有自己的 this。 不适合定义一个 对象的方法

当我们使用箭头函数的时候箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的。

箭头函数是不能提升的,所以需要在使用之前定义。

使用 const 比使用 var 更安全,因为函数表达式始终是一个常量。

如果函数部分只是一个语句,则可以省略 return 关键字和大括号 {},这样做是一个比较好的习惯

const x = (x, y) => { return x * y };

总结

(参数) => { 函数体 }

// 普通函数
let sum = function(a, b) {
    return a + b;
}

// 箭头函数
let sum1 = (a, b) => {
    return a + b;
}

省略包含参数的小括号

// 有效
let sum = (x) => {
    return x;
};
// 有效
let sum1 = x => {
    return x;
};
// 没有参数需要括号
let sum2 = () => {
    return 1;
};
// 有多个参数需要括号
let sum3 = (a, b) => {
    return a + b;
};

 省略包含函数体的大括号

// 有效
let sum = (a, b) => {
    return a + b;
};
// 有效
let sum1 = (a, b) => a + b; // 相当于 return a + b;
// 无效写法
let sum2 = (a, b) => return a + b;

 嵌入函数

let arr = [1, 2, 3, 4, 5];
arr.map(val => val * 2); // [2, 4, 6, 8, 10]

箭头函数不能使用arguments

// 普通函数
let sum = function() {
    return arguments.length;
}
sum(1, 2, 3); // 3

// 箭头函数
let sum1 = () => {
    return arguments.length;
}

sum1(1, 2); // Uncaught ReferenceError: arguments is not defined

虽然箭头函数中没有 arguments 对象,但可以在包装函数中把它提供给箭头函数:

function foo() {
    let bar = () => {
        console.log(arguments.length);
    }
    bar(); 
}
foo(5, 5, 5);  // 3

箭头函数中this 指向

let num = 11;
const obj1 = {
    num: 22,
    fn1: function() {
        let num = 33;
        const obj2 = {
            num: 44,
            fn2: () => {
                console.log(this.num);
            }
        }
        obj2.fn2();
    }
}
obj1.fn1(); // 22
 

fn2中得到的结果为:22

原因箭头函数没有this,箭头函数的this是继承父执行上下文里面的this ,这里箭头函数的执行上下文是函数fn1(),所以它就继承了fn1()的this,obj1调用的fn1,所以fn1的this指向obj1, 所以obj1.num 为 22。
注意:简单对象(非函数)是没有执行上下文的!
 

如果fn1也是个箭头函数呢?

let num = 11; 
const obj1 = {
    num: 22,
    fn1: () => {
        let num = 33;
        const obj2 = {
            num: 44,
            fn2: () => {
                console.log(this.num);
            }
        }
        obj2.fn2();
    }
}
obj1.fn1();

上述结果为undefined,因为fn1也是一个箭头函数,所以它就只能继续向上找也就是window了。

为什么是undefined而不是11呢?

这里涉及到var和let声明变量的一个区别:使用 let 在全局作用域中声明的变量不会成为 window 对象的属性,var 声明的变量则会(不过,let 声明仍然是在全局作用域中发生的,相应变量会在页面的生命周期内存续,所以使用window访问会为undefined):
 

var a = 1;
window.a; // 1

let b = 1;
window.b; // undefined

将let改成var后:

var num = 11; // 
const obj1 = {
    num: 22,
    fn1: () => {
        let num = 33;
        const obj2 = {
            num: 44,
            fn2: () => {
                console.log(this.num);
            }
        }
        obj2.fn2();
    }
}
obj1.fn1();

此时结果为window.num => 11

 

JavaScript 函数参数

参数传递

function foo(a, b) {
    console.log([a, b]);
}

foo(1, 2); // 输出 [1, 2]

这个例子中,a 和 b 属于函数中的局部变量,只能在函数中访问。调用函数时,传递的数据会根据位置来匹配对应,分别赋值给 a 和 b

创建函数时,function 函数名 后面括号中设定的参数被称为形参;调用函数时,函数名后面括号中传入的参数被称为实参

 

因为形参是已声明的变量,所以不能再用 let 和 const 重复声明

function foo(a, b) {
    let a = 1; // 报错,a 已声明
    const b = 1; // 报错,b 已声明
}

从一个变量赋值到另一个变量

function add(num) {
    return num + 1;
}

let count = 5;
let result = add(count); // 此处参数传递过程可以看作是 num = count

console.log(count); // 5
console.log(result); // 6

引用值: 

function setName(obj) {
    obj.name = “小明“;
}

let person = {};

setName(person); // 此处参数传递的过程可以看作是 obj = person;
console.log(person); // {name: “小明“}

理解参数

JavaScript 中的函数既不会检测参数的类型,也不会检测传入参数的个数。定义函数时设置两个形参,不意味着调用时必须传入两个参数。实际调用时不管是传了一个还是三个,甚至不传参数也不会报错。

所有函数(非箭头)中都有一个名为 arguments 的特殊的类数组对象(不是 Array 的实例),它保存着所有实参的副本,我们可以通过它按照数组的索引访问方式获取所有实参的值,也可以访问它的 arguments.length 属性来确定函数实际调用时传入的参数个数。

function foo(a, b) {
    console.log(arguments[0]);
    console.log(arguments[1]);
    console.log(arguments.length);
}

foo(10, 20); // 依次输出 10、20、2 

将对象属性用作实参

当一个函数包含的形参有多个时,调用函数就成了一种麻烦,因为你总是要保证传入的参数放在正确的位置上,有没有办法解决传参顺序限制呢?

由于对象属性是无序的,通过属性名来确定对应的值。因此可以通过传入对象的方式,以对象中的属性作为真正的实参,这样参数的顺序就无关紧要了。

function foo(obj) {
    console.log(obj.name, obj.sex, obj.age);
}

foo({ sex: ‘男’, age: 18, name: ‘小明‘ }); // 小明 男 18

参数默认值

如果调用函数时缺少提供实参,那么形参默认值为 undefined

时候我们想要设置特定的默认值,在 ES6 之前还不支持显式地设置默认值时候,只能采用变通的方式

function sayHi(name) {
    name = name || ‘everyone’;
    
    console.log( ‘Hello ‘ + name + ‘!’);
}

sayHi(); // 输出 ‘Hello everyone!’ 

// if 语句判断
function sayHi(name) {
    if (name === undefined) {
        name = ‘everyone’;
    }
    
    console.log( ‘Hello ‘ + name + ‘!’);
}

// 三元表达式判断
function sayHi(name) {
    name =  (name !== undefined) ? name : ‘everyone’;
    
    console.log( ‘Hello ‘ + name + ‘!’);
}

ES6 就方便了许多,因为它支持显式的设置默认值方式

function sayHi(name = ‘everyone’) { // 定义函数时,直接给形参赋值
    console.log( ‘Hello ‘ + name + ‘!’);
}

sayHi(); // 输出 ‘Hello everyone!’ 
sayHi(‘Tony’); // 输出 ‘Hello Tony!’ 
sayHi(undefined); // 输出 ‘Hello everyone!’

参数默认值的位置

function fn(x, y = 2) {
    console.log([x, y]);
}

fn(); // 输出 [undefined, 2]
fn(1); // 输出 [1, 2]
fn(1, 1) // 输出 [1, 1]

参数的收集展开

ES6 提供了**剩余参数(rest)**的语法...变量名),它可以收集函数多余的实参(即没有对应形参的实参),这样就不再需要使用 arguments 对象来获取了。形参使用了 ... 操作符会变成一个数组,多余的实参都会被放进这个数组中。

剩余参数基本用法

function sum(a, …values) {
 
    for (let val of values) {
        a += val;
    }
    
    return a;
}

sum(0, 1, 2, 3); // 6

参数位置 

// 报错
function fn1(a, …rest, b) {
    console.log([a, b, rest]);

// 正确写法
function fn2(a, b, …rest) {
    console.log([a, b, rest]);
}

fn2(1, 2, 3, 4) // 输出 [1, 2, [3, 4]]

 

function sum(…values) {
    let sum = 0;
    
    for (let val of values) {
        sum += val;
    }
    
    return sum;
}

let arr = [1, 2, 3, 4];

sum(arr); // “01,2,3,4”

把所有传进来的数值累加,如果直接传入一个数组,就得到我们想要的结果

sum.apply(null, arr); // 10

sum(…arr); // 10  // 相当于 sum(1,2,3,4);

sum(-1, …arr); // 9
sum(…arr, 5); // 15
sum(-1, …arr, 5); // 14
sum(-1, …arr, …[5, 6, 7]); // 27

JavaScript 对象

对象只是一种特殊的数据。对象拥有属性方法

创建了对象的一个新实例,并向其添加了四个属性

JavaScript 对象就是一个 name:value 集合

person=new Object();
person.firstname=”John”;
person.lastname=”Doe”;
person.age=50;
person.eyecolor=”blue“;

{ name1 : value1, name2 : value2,…nameN : valueN }

 

 

原文地址:https://blog.csdn.net/qq_44438941/article/details/132731514

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_31614.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注