javascript 基础

JavaScript简介

js是脚本语言,可插入 HTML 页面的编程代码。js直接写入html输出流,只能在html输出中使用document.write,如果在文档加载后使用该方法,会覆盖整个文档。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
<body>

 <p>
   JavaScript 能够直接写入 HTML 输出流中:
 </p>
 <script>
  document.write("<h1>This is a heading</h1>");
  document.write("<p>This is a paragraph.</p>");
 </script>

 <p>
  您只能在 HTML 输出流中使用 <strong>document.write</strong>。
  如果您在文档已加载后使用它(比如在函数中),会覆盖整个文档。
 </p>

 <button onclick="myFunction()">点击这里</button>

  <script>
  function myFunction()
  {
  document.write("调用了函数,文档被重写");
  }
  </script>

</body>
 </html>

在上述代码中,如果点击按钮,页面文档会被重写。

html的js代码必须位于script标签之间,可放置在body和head部分中。或者同时存在于两个部分中,也可以把脚本保存在外部的文件中。外部脚本布恩那个包含script标签。

js输出

使用window.alert()弹出警告框,使用document.write()将内容写到html文档,使用innerHTML写到HTML元素,使用console.log()写入到浏览器的控制台。

alert()函数可以接受变量,并将变量值与其他字符串进行拼接,但不接受向字符串传参数。

ocument.write是直接写入到页面的内容流,如果在写之前没有调用document.open, 浏览器会自动调用open。每次写完关闭之后重新调用该函数,会导致页面被重写。

console.log()依次传入不定数量个参数,%s 字符串(整数、小数也可以打印) ,%d 整数, %f 小数 ,%o 对象 ,%c 后面字符串的样式。alert()函数不能用。

js语法

js语法规则定义语言结构,轻量级函数优先。在编程语言中,一般固定值为字面量,数字字面量可以是整数或者是小数,字符串字面量可以使用单引号或者双引号,表达式字面量用于计算,数组字面量定义一个数组,对象字面量定义一个对象,函数字面量定义一个函数。js使用var来定义变量,使用等号为变量赋值,在html中,js向浏览器发出命令,语句通过;分隔。

js语句标识符

语句描述
break用于跳出循环。
catch语句块,在 try 语句块执行出错时执行 catch 语句块。
continue跳过循环中的一个迭代。
do … while执行一个语句块,在条件语句为 true 时继续执行该语句块。
for在条件语句为 true 时,可以将代码块执行指定的次数。
for … in用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。
function定义一个函数
if … else用于基于不同的条件来执行不同的动作。
return退出函数
switch用于基于不同的条件来执行不同的动作。
throw抛出(生成)错误 。
try实现错误处理,与 catch 一同使用。
var声明一个变量。
while当条件语句为 true 时,执行语句块。

3种注释的快捷键

1.单行注释:用于注释一行内容快捷键:CTRL+/

2.多行注释:用于一次性给多行代码注释,也可以使用单行注释只不过要选中多行快捷键:CTRL+shift+/

3.文本注释快捷键:/**+回车

js变量命名规则

只能以字母,数字,下划线,$,且不能以数字开头;字母区分大小写;js内部已占用的单词(关键词或保留字)不允许使用。可以在一条语句中声明很多变量,该语句以 var 开头,并使用逗号分隔变量即可。一条语句中声明的多个变量不可以同时赋同一个值。重新声明 JavaScript 变量,该变量的值不会丢失。JavaScript 版本 (ES6) 允许我们使用 const 关键字来定义一个常量,使用 let 关键字定义限定范围内作用域的变量

没有声明name,console.log(name)不报错,是因为window中含有name。使用var关键字进行显式声明的变量是做为局部变量,在全局范围内声明的变量为全局变量;而没有用var关键字,使用直接赋值方式声明的是全局变量(全局对象属性),当我们使用访问一个没有声明的变量时,JS会报错;而当我们给一个没有声明的变量赋值时,JS不会报错,相反它会认为我们是要隐式声明一个全局变量,首先,它会尝试在当前作用域链(如在方法中声明,则当前作用域链代表全局作用域和方法局部作用域)中解析 name; 如果在任何当前作用域链中找到name,则会执行对name属性赋值; 如果没有找到name,它才会在全局对象(即当前作用域链的最顶层对象,如window对象)中创造name属性并赋值。Javascript的变量声明、创建属性以及每个Javascript中的每个属性都有一定的标志说明它们的属性----如只读(ReadOnly)不可枚举(DontEnum)不可删除(DontDelete)等等。 由于变量声明自带不可删除属性,比较var name = ‘muzidigbig’ 跟 name = ‘muzidigbig’,前者是变量声明,带不可删除属性,因此无法被删除;后者为全局变量的一个属性,因此可以从全局变量中删除。

在js中,在函数内部声明的为局部变量,在函数外部声明的为全局变量。

js数据类型。值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。引用数据类型:对象(Object)、数组(Array)、函数(Function)。还有两个特殊的对象:正则(RegExp)和日期(Date)。Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。

数组有四种方式

var arr1 = new Array('a', 'b', 'c');    //这是一个预定义的数组,在创建时初始化
var arr2 = ['a', 'b', 'c' ];       //同样是在创建时初始化,但是这种创建更为简洁直观
var arr3 = new Array( );   var arr4 = [ ];     //这两种是创建空的数组

变量定义虽然为数组格式,typeof返回的数据类型还是object。

对象属性的键值对通常写法为name:value(键与值以冒号分隔)。在对象方法中,访问属性将作为一个定义函数的字符串返回。可以通过两种方式访问对象属性,person.lastName或者person[‘lastName’]

js函数,带有返回值的函数,返回调用它的地方,可以通过return语句就可以实现。js变量的生命期从它们被声明的时间开始,局部变量会在函数运行以后被删除,全局变量会在页面关闭后被删除,把值赋给尚未声明的变量,该变量将被自动作为 window 的一个属性。

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

函数内未声明,在函数没被调用前,函数内的未声明变量在全局不存在。

js作用域采用静态作用域

js事件

事件描述
onchangeHTML 元素改变
onclick用户点击 HTML 元素
onmouseover鼠标指针移动到指定的元素上时发生
onmouseout用户从一个 HTML 元素上移开鼠标时发生
onkeydown用户按下键盘按键
onload浏览器已完成页面的加载

js字符串

代码输出
单引号
"双引号
\反斜杠
\n换行
\r回车
\ttab(制表符)
\b退格符
\f换页符

JavaScript 字符串是原始值,可以使用字符创建: var firstName = “John”

但我们也可以使用 new 关键字将字符串定义为一个对象: **var firstName = new String(“John”)**不要创建 String 对象。它会拖慢执行速度,并可能产生其他副作用

js算术运算符

++自增。x=++y,x为6,y为6;x=y++,x为5,y为6.–同理。

用于字符串的+运算符,如果想增加空格,可在字符串中插入,后者把空格插入表达式中“ ”。如果数字和字符串相加,结果会成为字符串。

空文本+数字得到的运算结果就是把数字转成字符串。html会压缩空格, 所以直观上显示的是字符串,没有显示空格。

js中switch语句,:首先设置表达式 n(通常是一个变量)。随后表达式的值会与结构中的每个 case 的值做比较。如果存在匹配,则与该 case 关联的代码块会被执行。请使用 break 来阻止代码自动地向下一个 case 运行。

for循环

for (语句 1; 语句 2; 语句 3)
{
    被执行的代码块
}

执行顺序:语句1>2>代码块>3。语句1是可选的,语句2也是可选的,如果您省略了语句 2,那么必须在循环内提供 break。否则循环就无法停下来。这样有可能令浏览器崩溃。语句3也是可选的。

for in 循环

for in以任意顺序遍历一个对象的除symbol以外的可枚举属性,for in不仅可以遍历对象的额属性,还可以遍历数组。

1.index索引为字符串型数字,不能直接进行几何运算
2.遍历顺序有可能不是按照实际数组的内部顺序
3.使用for in会遍历数组所有的可枚举属性,包括原型。例如上栗的原型方法method和name属性。 所以for in更适合遍历对象,不要使用for in遍历数组。

  • for : 比较适合遍历数组,字符串等等。
  • for in : 比较适合遍历对象,遍历对象时使用这个再合适不过了。
  • while : while 的话,与 for 的使用场景差不多。唯一不同的是,遍历的条件必须满足。
  • do while : 至少执行一边的循环,遍历数组和字符串也是很方便。

while遍历数组的例子中,如果数组中有 0,null,false,undefined 或者空字符串等在 js 中被认为等价于 false 的值,会提前结束遍历。改成判断数组长度即可避免该问题

break 语句用于跳出循环。continue 用于跳过循环中的一个迭代。continue 语句(带有或不带标签引用)只能用在循环中。break 语句(不带标签引用),只能用在循环或 switch 中。

数组是一种特殊的对象类型。 因此 typeof [1,2,3,4] 返回 object。null是一个只有一个值的特殊类型。表示一个空对象引用。typeof 检测 null 返回是object。在 JavaScript 中, undefined 是一个没有设置值的变量。typeof 一个没有值的变量会返回 undefined

1、定义

  • (1)undefined:是所有没有赋值变量的默认值,自动赋值。
  • (2)null:主动释放一个变量引用的对象,表示一个变量不再指向任何对象地址。

2、何时使用null?

当使用完一个比较大的对象时,需要对其进行释放内存时,设置为 null。

3、null 与 undefined 的异同点是什么呢?

共同点:都是原始类型,保存在栈中变量本地。

不同点:

(1)undefined——表示变量声明过但并未赋过值。

它是所有未赋值变量默认值,例如:

var a;    // a 自动被赋值为 undefined

(2)null——表示一个变量将来可能指向一个对象。

一般用于主动释放指向对象的引用,例如:

var emps = ['ss','nn'];
emps = null;     // 释放指向数组的引用

4、延伸——垃圾回收站

它是专门释放对象内存的一个程序。

  • (1)在底层,后台伴随当前程序同时运行;引擎会定时自动调用垃圾回收期;
  • (2)总有一个对象不再被任何变量引用时,才释放。

js类型转换

  • NaN 的数据类型是 number
  • 数组(Array)的数据类型是 object
  • 日期(Date)的数据类型为 object
  • null 的数据类型是 object
  • 未定义变量的数据类型为 undefined

如果对象是 JavaScript Array 或 JavaScript Date ,我们就无法通过 typeof 来判断他们的类型,因为都是 返回 object。

"John".constructor                 // 返回函数 String()  { [native code] }
(3.14).constructor                 // 返回函数 Number()  { [native code] }
false.constructor                  // 返回函数 Boolean() { [native code] }
[1,2,3,4].constructor              // 返回函数 Array()   { [native code] }
{name:'John', age:34}.constructor  // 返回函数 Object()  { [native code] }
new Date().constructor             // 返回函数 Date()    { [native code] }
function () {}.constructor         // 返回函数 Function(){ [native code] }

undefined和null没有constructor属性,一般应先检测值是否为undefined和null,然后再调用constructor。数值直接量不能直接读取constructor属性,应该先把它转换为对象再调用。解释代码时对于“1.toString()”认为“.”是浮点符号,但因小数点后面的字符是非法的,所以报语法错误;而后面的“1…toString()和1.2.toStirng()”写法,javascript引擎认为第一个“.”小数点,的二个为属性访问语法,所以都能正确解释执行;对于“(1).toStirng()”的写法,用“()”排除了“.”被视为小数点的语法解释,所以这种写法能够被解释执行;

toSring是Object类型的原型方法

var o = {}; //对象
var a = [1,2]; //数组
var f = function(){}; //函数
console.log(o.toString()); //表示为 "[object Object]"
console.log(a.toString()); //表示为 "1,2"
console.log(f.toString()); //表示为 "function (){}"

不同类型对象调用 toString() 方法时返回的字符串格式并不统一,这是因为不同类型的子类在继承 Object 的原型方法 toString,时重写了该方法。

**String()**可以将null和undefined转换为字符串,但是没法转进制字符串

一元运算符+,可用于将变量转换为数字。

当 JavaScript 尝试操作一个 “错误” 的数据类型时,会自动转换为 “正确” 的数据类型。

加号“+”作为二元操作符(binary)并且其中一个操作数为字符串类型时,另一个操作数将会被无条件转为字符串类型,对于基础类型,会直接转为与字面量相一致的字符串类型,而对于复合类型,会先试图调用对象的valueOf()方法,如果此方法返回值是引用类型,则接着再调用其toString()方法,最后将返回值转为字符串类型。

当数字在逻辑环境中执行时,会自动转为布尔类型。0和NaN会自动转为false,其余数字都被认为是true

当字符串在逻辑环境中执行时,也会被转为布尔类型。空字符串会被转为false,其它字符串都会转为true

undefined和null在逻辑环境中执行时,都被认为是false

当对象在逻辑环境中执行时,只要当前引用的对象不为空,都会被认为是true。如果一个对象的引用为null,根据上面的介绍,会被转换为false。虽然使用typeof检测null为"object",但它并不是严格意义上的对象类型,只是一个对象空引用的标识。

正是由于对象总被认为是true,使用基础类型的包装类时,要特别小心

复制代码
// 以下包装对象都被认为是true

if (new Boolean(false)) {
    console.log('true');    // output: true
} else {
    console.log('false');
}

if (new Number(0)) {
    console.log('true');    // output: true
} else {
    console.log('false');
}

if (new Number(NaN)) {
    console.log('true');    // output: true
} else {
    console.log('false');
}

if (new String('')) {
    console.log('true');    // output: true
} else {
    console.log('false');
}
var num = 10;//基本类型
var num = Number("10");//将包装类转换为基本类型
var num = new Number("10");//基本包装类型

JS为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象

String()可以基本数据类型字符串转换为String对象

Number()可以基本数据类型数字转换为Number对象

Boolean()可以基本数据类型布尔值转换为Boolean对象

三个包装类的是给后台使用的,比如浏览器,当我们调用比如字符串的方法时,后台会临时通过包装类来创建对象,然后通过对象调用方法,完成之后就会立即销毁

使用包装类实例的时候,引擎只会判断其引用是否存在,不会判断内部的值

我们也可以不使用new关键字,而是显示的调用其包装类函数,将这些值转为布尔类型。

复制代码
if (Boolean(false)) {
    console.log('true');
} else {
    console.log('false');    // output: false
}

if (Number(0)) {
    console.log('true');
} else {
    console.log('false');    // output: false
}

if (Number(NaN)) {
    console.log('true');
} else {
    console.log('false');    // output: false
}

if (String('')) {
    console.log('true');
} else {
    console.log('false');    // output: false
}
复制代码

对于Boolean类,有一个特别需要注意的是,当传入一个字符串时,它不会去解析字符串内部的值,而是做个简单地判断,只要不是空字符串,都会被认为是true

当**加号“+”作为一元操作符(unary)**时,引擎会试图将操作数转换为数字类型,如果转型失败,则会返回NaN

加号“+”作为二元操作符时,我们上面也提到过,如果一个操作数为字符串,则加号“+”作为字符串连接符,但如果两个操作数都不是字符串类型,则会作为加法操作符,执行加法操作,这个时候,其他数据类型也会被转为数字类型

当**减号“-”作为一元操作符(unary negation)**时,也会将操作数转换为数字,只不过转换的结果与上面相反,合法的数字都被转为负值

除加号“+”以外的其他二元操作符,都会将操作数转为数字,字符串也不例外

js正则表达式

/正则表达式主体/修饰符(可选)

正则表达式通常用于两个字符串方法search() 和 replace()。search方法用于检索字符串中的指定子字符串,并返回子串的起始位置。replace方法用于替换字符串

在js中,RegExp对象是一个预定义了属性和方法的正则表达式对象。test()用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false。exec() 方法用于检索字符串中的正则表达式的匹配。该函数返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。

js错误

try 语句测试代码块的错误。

catch 语句处理错误。

throw 语句创建自定义错误。

finally 语句在 try 和 catch 语句之后,无论是否有触发异常,该语句都会执行。

js声明提升

函数声明和变量声明都会被提升,但是函数会首先被提升,然后才是变量。函数声明直接把整个函数提升到执行环境的最顶端,匿名函数不存在函数提升,因为函数名称使用变量表示,只存在变量提升,

js严格模式

“use strict”

  • 消除代码运行的一些不安全之处,保证代码运行的安全;
  • 提高编译器效率,增加运行速度;
  • 为未来新版本的Javascript做好铺垫。

js误区

64位浮点型数据的精准度很难确定

var x = 0.1;
var y = 0.2;
var z = x + y            // z 的结果为 0.30000000000000004
if (z == 0.3)            // 返回 false

js表单

js表单验证中为何使用οnsubmit="return validateForm()"而不是οnsubmit=“validateForm()”。

在表单中加上οnsubmit=“return false”可以组织表单提交,onsubmit属性就像是这个html对象的一个方法名,其值(一字符串)就是其方法体,默认返回true。οnsubmit="validateForm()效果为

Form.prototype.onsubmit = function() {

    submitTest();

};

js this关键字

  • 在方法中,this 表示该方法所属的对象。
  • 如果单独使用,this 表示全局对象。
  • 在函数中,this 表示全局对象。
  • 在函数中,在严格模式下,this 是未定义的(undefined)。
  • 在事件中,this 表示接收事件的元素。
  • 类似 call() 和 apply() 方法可以将 this 引用到任何对象。

只要函数被赋给另一个变量,this的指向就会变。this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁实际上this的最终指向的是那个调用它的对象

函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window

函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象

函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

js let和const

let声明的变量只在let命令的代码块内有效,const声明一个只读的常量,函数内使用 var 声明的变量只能在函数内容访问,如果不使用 var 则是全局变量。使用 var 关键字声明的变量不具备块级作用域的特性,它在 {} 外依然能被访问到。使用 var 关键字重新声明变量可能会带来问题。在块中重新声明变量也会重新声明块外的变量。let 关键字就可以解决这个问题,因为它只在 let 命令所在的代码块 {} 内有效。使用 let 关键字声明的全局作用域变量不属于 window 对象,let 关键字定义的变量则不可以在使用后声明,也就是变量需要先声明再使用。

  • const声明的常量必须初始化,而let声明的变量不用
  • const 定义常量的值不能通过再赋值修改,也不能再次声明。而 let 定义的变量值可以修改。

const 定义的变量并非常量,并非不可变,它定义了一个常量引用一个值。使用 const 定义的对象或者数组,其实是可变的,但是我们不能对常量对象重新赋值。

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

const car = {type:"Fiat", model:"500", color:"white"};
car = {type:"Volvo", model:"EX60", color:"red"};    // 错误

js json

json用于存储和传输数据格式,通常用于服务端向网页传递数据。

json语法规则

  • 数据为 键/值 对。(键/值 对包括字段名称,在双引号中)
  • 数据由逗号分隔。
  • 大括号保存对象 (对象可以保存多个键/值对)
  • 方括号保存数组 (数组可以包含对象)

js void

javascript:void(0) 中最关键的是 void 关键字, void 是 JavaScript 中非常重要的关键字,该操作符指定要计算一个表达式但是不返回值。

herf="#"与herf=“javascript:void(0)”的区别

# 包含了一个位置信息,默认的锚是**#top** 也就是网页的上端。而javascript:void(0), 仅仅表示一个死链接。在页面很长的时候会使用 # 来定位页面的具体位置,格式为:# + id

js 异步编程

异步就是从主线程发射一个子线程来完成任务。常常用子线程来完成一些可能消耗时间足够长以至于被用户察觉的事情,比如读取一个大文件或者发出一个网络请求。因为子线程独立于主线程,所以即使出现阻塞也不会影响主线程的运行。但是子线程有一个局限:一旦发射了以后就会与主线程失去同步,我们无法确定它的结束,如果结束之后需要处理一些事情,比如处理来自服务器的信息,我们是无法将它合并到主线程中去的。为了解决这个问题,JavaScript 中的异步操作函数往往通过回调函数来实现异步任务的结果处理。

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

setTimeout 就是一个消耗时间较长(3 秒)的过程,它的第一个参数是个回调函数,第二个参数是毫秒数,这个函数执行之后会产生一个子线程,子线程会等待 3 秒,然后执行回调函数 “print”,在命令行输出 “RUNOOB!”。

除了 setTimeout 函数以外,异步回调广泛应用于 AJAX 编程。

js promise

promise是异步编程的一种解决方案,es6规定,Promise对象是一个构造函数,用来生成Promise实例

const promise = new Promise(function(resolve,reject){
    if(/* 异步操作成功 */){
        resolve(value);
    }else{
        reject(error);
    }
})

Promise构造函数接受一个函数为参数,该函数的两个参数分别为resolve和reject,它们是两个函数,由javascript引擎提供,不用自己部署。resolve函数的作用是,将Promise对象的状态从未完成变为成功,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从未完成变为失败,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

promise.then(function(value){},function(error){})

生成promise实例后,可以使用then方法,该方法可以接收连个回调函数作为参数,第一个回调函数是状态为resolve时调用,第二个回调函数时状态为reject时调用,两个函数都是可选的,都接收Promise对象传出的值作为参数。

function timeout(ms){
    return new Promise((resove,reject)=>{
        setTimeout(resove,ms.'done');
    })
}
timeout(100).then((value)=>{
    console.log(value);
})

在setTimeout中,resove表示函数,ms为时间,’done’为传入resove的参数。

Promise新建后会立即执行

let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');

// Promise
// Hi!
// resolved

如果调用resolve函数和reject函数时带有参数,那么他们的参数会被传递给回调函数,reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个Promise 实例

Promise实例具有then方法,它的作用时为Promise实例添加状态改变时的回调函数,then方法返回的是一个新的Promise实例,因此可以采用链式写法,回调函数完成以后,会将放回结果作为参数,传入第二个回调函数,前一个回调函数的返回可能还是Promise对象,这时后一个回调函数就会等Promise对象的状态发生变化,才能被调用。

Promise实例的catch方法,如果对象状态变为resolved,则会调用then()方法指定的回调函数;如果异步操作抛出错误,状态就会变为rejected,就会调用catch()方法指定的回调函数,处理这个错误。另外,then()方法指定的回调函数,如果运行中抛出错误,也会被catch()方法捕获。如果Promise状态已经变成了resolved,再抛出异常是无效的。不要在then()方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法。如果没有使用catch()方法指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应。catch()方法返回的还是一个 Promise 对象,因此后面还可以接着调用then()方法。catch()方法指定的回调函数,会接着运行后面那个then()方法指定的回调函数。如果没有报错,则会跳过catch()方法。要是then()方法里面报错,就与前面的catch()无关

Promise.resolve()
.catch(function(error) {
  console.log('oh no', error);
})
.then(function() {
  console.log('carry on');
});

Promise实例的finally方法,指定不管 Promise 对象最后状态如何,都会执行的操作。finally本质是then方法的特例。

promise
.finally(() => {
  // 语句
});

// 等同于
promise
.then(
  result => {
    // 语句
    return result;
  },
  error => {
    // 语句
    throw error;
  }
);

finally实现

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

Promise.all方法用于将多个Promise实例包装成一个新的Promise实例

const p = Promise.all([p1, p2, p3]);

Promise.all接收一个数组为参数,参数可以不是数组,但必须有 Iterator 接口,且返回的每个成员都是 Promise 实例

p的状态由p1p2p3决定,分成两种情况。

(1)只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1p2p3之中有一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()catch方法。

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.race([p1,p2,p3]);

只要p1p2p3之中有一个实例率先改变状态,p的状态就跟着改变

Promise.allSettled()方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。该方法返回的新的 Promise 实例,一旦发生状态变更,状态总是fulfilled,不会变成rejected。状态变成fulfilled后,它的回调函数会接收到一个数组作为参数,该数组的每个成员对应前面数组的每个 Promise 对象。

Promise.any()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回,要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。Promise.any()Promise.race()方法很像,只有一点不同,就是Promise.any()不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束。

将现有对象转为 Promise 对象,Promise.resolve()方法就起到这个作用.如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。thenable对象指的是具有then方法的对象,Promise.resolve()方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then()方法。如果参数是一个原始值,或者是一个不具有then()方法的对象,则Promise.resolve()方法返回一个新的 Promise 对象,状态为resolvedPromise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。所以,如果希望得到一个 Promise 对象,比较方便的方法就是直接调用Promise.resolve()方法。

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejectedPromise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。

js函数

js使用function定义函数,分号是用来分隔可执行JavaScript语句。由于函数声明不是一个可执行语句,所以不以分号结束。函数可以在声明前调用,函数可以自动调用,如果表达式后面紧跟(),则会自动调用,不能自调用声明的函数。函数定义为对象的属性,称之为对象方法,函数用于创建新的对象,称之为对象的构造函数。

箭头函数更简洁

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

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

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

() => {函数声明}

JavaScript 函数有个内置的对象 arguments 对象。argument 对象包含了函数调用的参数数组。call()apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象本身。apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入。

变量声明时如果不使用 var 关键字,那么它就是一个全局变量,即便它在函数内定义。全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。

而在函数内部声明的变量,只在函数内部起作用。这些变量是局部变量,作用域是局部性的;函数的参数也是局部性的,只在函数内部起作用。

所有函数都能访问全局变量。 实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。

js类

使用 class 关键字来创建一个类,类体在一对大括号 {} 中,我们可以在大括号 {} 中定义类成员的位置,如方法或构造函数。每个类中包含了一个特殊的方法 constructor(),它是类的构造函数,这种方法用于创建和初始化一个由 class 创建的对象。

构造方法是一种特殊的方法:

  • 构造方法名为 constructor()。
  • 构造方法在创建新对象时会自动执行。
  • 构造方法用于初始化对象属性。
  • 如果不定义构造方法,JavaScript 会自动添加一个空的构造方法。

类继承使用 extends 关键字。继承允许我们依据另一个类来定义一个类。super() 方法用于调用父类的构造函数。当创建一个类时,不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类(父类),新建的类称为派生类(子类)。getter 和 setter 可以使得我们对属性的操作变的很灵活。类中添加 getter 和 setter 使用的是 get 和 set 关键字。

首先需要声明你的类,然后再访问它,函数声明会提升,类声明不会。

静态方法是使用 static 关键字修饰的方法,又叫类方法,属于类的,但不属于对象,在实例化对象之前可以通过 类名.方法名 调用静态方法。静态方法不能在对象上调用,只能在类中调用。如果你想在对象 noob 中使用静态方法,可以作为一个参数传递给它

class Runoob {
  constructor(name) {
    this.name = name;
  }
  static hello(x) {
    return "Hello " + x.name;
  }
}
let noob = new Runoob("123");
document.getElementById("demo").innerHTML = Runoob.hello(noob);

js html dom

当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。

在 DOM 中查找 HTML 元素的最简单的方法,是通过使用元素的 id。

var x=document.getElementById("intro");

查找 id=“main” 的元素,然后查找 id=“main” 元素中的所有

元素

var x=document.getElementById("main");
var y=x.getElementsByTagName("p");

通过类名查找

var x=document.getElementsByClassName("intro");

修改 HTML 内容的最简单的方法是使用 innerHTML 属性。

document.getElementById(id).innerHTML=新的 HTML

改变 HTML 元素的属性,请使用这个语法

document.getElementById(id).attribute=新属性值

改变 HTML 元素的样式,请使用这个语法

document.getElementById(id).style.property=新样式

addEventListener() 方法用于向指定元素添加事件句柄。addEventListener() 方法添加的事件句柄不会覆盖已存在的事件句柄。你可以向一个元素添加多个事件句柄。你可以向同个元素添加多个同类型的事件句柄,如:两个 “click” 事件。你可以向任何 DOM 对象添加事件监听,不仅仅是 HTML 元素。如: window 对象。addEventListener() 方法可以更简单的控制事件(冒泡与捕获)。当你使用 addEventListener() 方法时, JavaScript 从 HTML 标记中分离开来,可读性更强, 在没有控制HTML标记时也可以添加事件监听。你可以使用 removeEventListener() 方法来移除事件的监听。

事件传递有两种方式:冒泡与捕获。事件传递定义了元素事件触发的顺序。 如果你将

元素插入到

元素中,用户点击

元素, 哪个元素的 “click” 事件先被触发呢?在 冒泡 中,内部元素的事件会先被触发,然后再触发外部元素,即:

元素的点击事件先触发,然后会触发

元素的点击事件。在 捕获 中,外部元素的事件会先被触发,然后才会触发内部元素的事件,即:
元素的点击事件先触发 ,然后再触发

元素的点击事件。

默认值为 false, 即冒泡传递,当值为 true 时, 事件使用捕获传递。

要创建新的 HTML 元素 (节点)需要先创建一个元素,然后在已存在的元素中添加它。

<div id="div1">
<p id="p1">这是一个段落。</p>
<p id="p2">这是另外一个段落。</p>
</div>
 
<script>
var para = document.createElement("p");
var node = document.createTextNode("这是一个新的段落。");
para.appendChild(node);
 
var element = document.getElementById("div1");
element.appendChild(para);
</script>

appendChild() 方法,它用于添加新元素到尾部。如果我们需要将新元素添加到开始位置,可以使用 insertBefore() 方法

要移除一个元素,你需要知道该元素的父元素。从父元素中移除子节点

parent.removeChild(child)

已知要查找的子元素,然后查找其父元素,再删除这个子元素

var child = document.getElementById("p1");
child.parentNode.removeChild(child);

可以使用 replaceChild() 方法来替换 HTML DOM 中的元素。

getElementsByTagName() 方法返回 HTMLCollection对象。HTMLCollection 对象类似包含 HTML 元素的一个数组。HTMLCollection 看起来可能是一个数组,但其实不是。你可以像数组一样,使用索引来获取元素。HTMLCollection 无法使用数组的方法: valueOf(), pop(), push(), 或 join() 。

HTMLCollection 是 HTML 元素的集合。NodeList 是一个文档节点的集合。NodeList 与 HTMLCollection 有很多类似的地方。NodeList 与 HTMLCollection 都与数组对象有点类似,可以使用索引 (0, 1, 2, 3, 4, …) 来获取元素。NodeList 与 HTMLCollection 都有 length 属性。HTMLCollection 元素可以通过 name,id 或索引来获取。NodeList 只能通过索引来获取。只有 NodeList 对象有包含属性节点和文本节点。

js prototype

有的 JavaScript 对象都会从一个 prototype(原型对象)中继承属性和方法

img

image.png

f1为Foo构造函数的实例,实例的隐式原型指向构造函数Foo的显示原型。

构造函数Foo是由function创建,Foo的隐式原型指向Function的显示原型

Foo的显示原型也是对象,则Foo的显示原型的隐式原型指向Object的显示原型

js Number对象

js只有一种数字类型,可以使用也可以不使用小数点来书写,所有的js数字均为64位,所有的数字都是由浮点型类型,0到51存储数字,52到62存储指数,63存储符号。

img

js String

在字符串中查找字符串,可以使用indexOf()来定位字符串的某一个指定的字符首次出现的位置,如果没找到对应的字符函数返回-1。match()函数查找字符串中特定的字符,并且如果找到的话,返回这个字符,没找到就是null。replace()方法在字符串中用某些字符替换另一些字符。字符串大小写转换使用函数toUpperCase() / toLowerCase()。字符串使用split()函数转为数组。

js 计时事件

  • setInterval() - 间隔指定的毫秒数不停地执行指定的代码。
  • setTimeout() - 在指定的毫秒数后执行指定代码。

clearInterval() 方法用于停止 setInterval() 方法执行的函数代码

clearTimeout() 方法用于停止执行setTimeout()方法的函数代码。

js 对象

js Array对象

数组属性

constructor返回创建数组对象的原型函数。 它存在于每一个function的prototype属性中,这个constructor保存了指向function的一个引用。
1为Foo构造函数的实例,实例的隐式原型指向构造函数Foo的显示原型。

构造函数Foo是由function创建,Foo的隐式原型指向Function的显示原型

Foo的显示原型也是对象,则Foo的显示原型的隐式原型指向Object的显示原型

js Number对象

js只有一种数字类型,可以使用也可以不使用小数点来书写,所有的js数字均为64位,所有的数字都是由浮点型类型,0到51存储数字,52到62存储指数,63存储符号。

[外链图片转存中…(img-x2C99jzU-1666238610530)]

js String

在字符串中查找字符串,可以使用indexOf()来定位字符串的某一个指定的字符首次出现的位置,如果没找到对应的字符函数返回-1。match()函数查找字符串中特定的字符,并且如果找到的话,返回这个字符,没找到就是null。replace()方法在字符串中用某些字符替换另一些字符。字符串大小写转换使用函数toUpperCase() / toLowerCase()。字符串使用split()函数转为数组。

js 计时事件

  • setInterval() - 间隔指定的毫秒数不停地执行指定的代码。
  • setTimeout() - 在指定的毫秒数后执行指定代码。

clearInterval() 方法用于停止 setInterval() 方法执行的函数代码

clearTimeout() 方法用于停止执行setTimeout()方法的函数代码。

js 对象

js Array对象

数组属性

constructor返回创建数组对象的原型函数。 它存在于每一个function的prototype属性中,这个constructor保存了指向function的一个引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值