开始学习JavaScript!

开始学习JavaScript!

javaScript是一门用来实现用户交互的客户端脚本语言。

特点

  • 弱类型
  • 解释型
  • 基于对象(面向对象)
  • 事件驱动
  • 单线程异步机制

面向过程 VS 面向对象

面向过程(Procedure Oriented)和面向对象(Object Oriented,OO)都是对软件分析、设计和开发的一种思想,它指导着人们以不同的方式去分析、设计和开发软件。早期先有面向过程思想,随着软件规模的扩大,问题复杂性的提高,面向过程的弊端越来越明显的显示出来,出现了面向对象思想并成为目前主流的方式。两者都贯穿于软件分析、设计和开发各个阶段,对应面向对象就分别称为面向对象分析(OOA)、面向对象设计(OOD)和面向对象编程(OOP)。C语言是一种典型的面向过程语言,Java是一种典型的面向对象语言。

1.面向过程的基本概念

面向过程思想思考问题时,我们首先思考“怎么按步骤实现?”并将步骤对应成方法,一步一步,最终完成。 这个适合简单任务,不需要过多协作的情况下。

- 面向过程(Procedure Oriented)是一种以过程为中心的编程思想。
- 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。是一种思考问题的基础方法。
- 简单理解:面向过程就是任何事情都亲力亲为,很机械,像个步兵。

2.面向对象的基本概念

- 面向对象(Object Oriented)是软件开发方法中的一种;是一种对现实世界理解和抽象的方法;是思考问题相对高级的方法。
- 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
- 简单理解:面向对象就像战场上的指挥官,指挥战斗而不必知道具体执行的过程。
面向对象的三大特征:即封装、继承和多态性
封装
1.封装是指什么?
通常认为封装就是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口
我们在类中编写的方法就是对实现细节的封装,我们编写一个类就是对数据和数据操作的封装
2.面向对象的本质是什么?
其实面向对象的本质,就是把现实世界描绘成一系列完全自治、封闭的对象
3.那么封装的意义是什么?
其实就在于明确标识出允许外部使用的所有成员函数(比如Java实体类的get和set方法)和数据项(比如Java实体类的属性或者字段)
继承
1.什么是继承?
继承是从已有类 (基类或者父类)中得到继承信息,然后创建新类(子类或者派生类)的过程
简单理解,就是继承基类 (父类) 的方法,并做出自己的一些改变或者拓展
2.继承的好处是什么?
子类共性的方法或者属性可以直接使用父类的,而不需要自己再定义,只需做个性化拓展
继承让变化中的软件系统具有了一定的延续性
同时继承也是封装程序中可变因素的重要手段
多态性
1.什么是多态性?
很多资源上的定义是,多态性是指允许不同子类型的对象对同一消息作出不同的响应
简单来说就是用同样的对象引用调用同样的方法但是做了不同的事情
还有一种理解是,基于对象所属类的不同,外部对同一个方法调用后,而实际执行的逻辑不同
2.多态性案例解释
2-1 实现步骤
继承,方法重写,父类引用指向子类对象
3.多态的分类
3-1 多态分为哪几种?
多态分为运行时的多态性编译时的多态性
3-1 什么是运行编译时多态
方法重载 (overload) 是实现编译时的多态性 (也称前绑定) ,而方法重写 (override) 实现的是运行时的多态性 (也称后绑定)
3-2 什么是运行时多态?
如果将对象的方法视为对象向外界提供的服务,那么运行时的多态可以解释为:
当系统A去访问系统B提供的服务时,B系统有多种提供服务的方式,但一切对A系统来说都是透明的
就好比电动剃须刀是A系统,它的供电系统是B系统,B系统可以使用电池供电或者使用交流电,甚至可能是太阳能,A系统只会调用B类对象供电的方法,但并不了解供电系统的底层实现是什么,究竟通过何种方式获得了动力
运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事情:

方法重写:子类继承父类并重写父类中已有的或者抽象的方法
对象造型:用父类型引用子类型对象,这样同样的引用调用同样的方法时就会根据子类对象的不同而表现不同的行为

区别

面向过程强调的是功能行为,以函数为最小单位,考虑怎么做。
面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
面向过程的分析主体为解决问题的行为步骤,面向对象的分析主体为问题中的行动执行者和被执行者。

面向过程这种将事情拆成一系列步骤的行为会比较直接和高效
而面向对象将事物属性和方法抽象出来,虽然不如面向过程那么直接高效,但这样做的好处是让代码变得更加易于复用,给扩展功能和后期的维护带来了极大便利; 抽象其实就是将一类对象的共同特征给总结出来并构造类的过程,包括数据抽象和行为抽象两方面 (也就是Java实体类对象的属性和方法)

而且抽象只关心对象有哪些属性和行为,所以并不关注这些行为的细节是什么

组成

  • ECMAScript基础语法;JavaScript 的核心 ECMAScript 描述了该语言的语法和基本对象;

  • BOM浏览器对象模型;BOM 描述了与浏览器进行交互的方法和接口。

  • DOM文档对象模型;DOM 描述了处理网页内容的方法和接口;

    ECMAScript、DOM 和 BOM

    尽管 ECMAScript 是一个重要的标准,但它并不是 JavaScript 唯一的部分,当然,也不是唯一被标准化的部分。实际上,一个完整的 JavaScript 实现是由以下 3 个不同部分组成的:

ECMAScript

ECMAScript 并不与任何具体浏览器相绑定,实际上,它也没有提到用于任何用户输入输出的方法(这点与 C 这类语言不同,它需要依赖外部的库来完成这类任务)。那么什么才是 ECMAScript 呢?ECMA-262 标准(第 2 段)的描述如下:

“ECMAScript 可以为不同种类的宿主环境提供核心的脚本编程能力,因此核心的脚本语言是与任何特定的宿主环境分开进行规定的… …”
Web 浏览器对于 ECMAScript 来说是一个宿主环境,但它并不是唯一的宿主环境。事实上,还有不计其数的其他各种环境(例如 Nombas 的 ScriptEase,以及 Macromedia 同时用在 Flash 和 Director MX 中的 ActionScript)可以容纳 ECMAScript 实现。那么 ECMAScript 在浏览器之外规定了些什么呢?

简单地说,ECMAScript 描述了以下内容:
语法
类型
语句
关键字
保留字
运算符
对象
ECMAScript 仅仅是一个描述,定义了脚本语言的所有属性、方法和对象。其他语言可以实现 ECMAScript 来作为功能的基准,JavaScript 就是这样:

ECMAScript、JavaScript、ActionScript、ScriptEase
每个浏览器都有它自己的 ECMAScript 接口的实现,然后这个实现又被扩展,包含了 DOM 和 BOM(在以下几节中再探讨)。当然还有其他实现并扩展了 ECMAScript 的语言,例如 Windows 脚本宿主(Windows Scripting Host, WSH)、Macromedia 在 Flash 和 Director MX 中的 ActionScript,以及 Nombas ScriptEase。

1. ECMAScript 的版本

ECMAScript 分成几个不同的版本,它是在一个叫做 ECMA-262 的标准中定义的。和其他标准一样,ECMA-262 会被编辑和更新。当有了主要更新时,就会发布一个标准的新版。最新 ECMA-262 的版本是第三版,于 1999 年 12 月发布。

ECMA-262 的第一版在本质上与 Netscape 的 JavaScript 1.1 是一样,只是把所有与浏览器相关的代码删除了,此外还有一些小的调整。首先,ECMA-262 要求对 Unicode 标准的支持(以便支持多语言)。第二,它要求对象是平台无关的(Netscape 的 JavaScript 1.1 事实上有不同的对象实现,例如 Date 对象,是依赖于平台)。这是 JavaScript 1.1 和 1.2 为什么不符合 ECMA-262 规范第一版的主要原因。

ECMA-262 的第二版大部分更新本质上是编辑性的。这次标准的更新是为了与 ISO/IEC-16262 的严格一致,也并没有特别添加、更改和删除内容。ECMAScript 一般不会遵守第二版。

ECMA-262 第三版是该标准第一次真正的更新。它提供了对字符串处理、错误定义和数值输出的更新。同时,它还增加了正则表达式、新的控制语句、try…catch 异常处理的支持,以及一些为使标准国际化而做的小改动。一般来说,它标志着 ECMAScript 成为一种真正的编程语言。

2. 何谓 ECMAScript 符合性

在 ECMA-262 中,ECMAScript 符合性(conformance)有明确的定义。一个脚本语言必须满足以下四项基本原则:

符合的实现必须按照 ECMA-262 中所描述的支持所有的“类型、值、对象、属性、函数和程序语言及语义”(ECMA-262,第一页)
符合的实现必须支持 Unicode 字符标准(UCS)
符合的实现可以增加没有在 ECMA-262 中指定的“额外类型、值、对象、属性和函数”。ECMA-262 将这些增加描述为规范中未给定的新对象或对象的新属性
符合的实现可以支持没有在 ECMA-262 中定义的“程序和正则表达式语法”(意思是可以替换或者扩展内建的正则表达式支持)
所有 ECMAScript 实现必须符合以上标准。

3. Web 浏览器中的 ECMAScript 支持

含有 JavaScript 1.1 的 Netscape Navigator 3.0 在 1996 年发布。然后,JavaScript 1.1 规范被作为一个新标准的草案被提交给 EMCA。有了 JavaScript 轰动性的流行,Netscape 十分高兴地开始开发 1.2 版。但有一个问题,ECMA 并未接受 Netscape 的草案。在 Netscape Navigator 3.0 发布后不久,微软就发布了 IE 3.0。该版本的 IE 含有 JScript 1.0(微软自己的 JavaScript 实现的名称),原本计划可以与 JavaScript 1.1 相提并论。然后,由于文档不全以及一些不当的重复特性,JScript 1.0 远远没有达到 JavaScript 1.1 的水平。

在 ECMA-262 第一版定稿之前,发布含有 JavaScript 1.2 的 Netscape Navigator 4.0 是在 1997 年,在那年晚些时候,ECMA-262 标准被接受并标准化。因此,JavaScript 1.2 并不和 ECMAScript 的第一版兼容,虽然 ECMAScript 应该基于 JavaScript 1.1。

JScript 的下一步是 IE 4.0 中加入的 JScript 3.0(2.0 版是随 IIS 3.0 一起发布的,但并未包含在浏览器中)。微软大力宣传 JScript 3.0 是世界上第一个真正符合 ECMA 标准的脚本语言。而那时,ECMA-262 还没有最终定稿,所以 JScript 3.0 也遭受了和 JavaScript 1.2 同样的命运 - 它还是没能符合最终的 ECMAScript 标准。

Netscape 选择在 Netscape Navigator 4.06 中升级它的 JavaScript 实现。JavaScript 1.3 使 Netscape 终于完全符合了 ECMAScript 第一版。Netscape 加入了对 Unicode 标准的支持,并让所有的对象保留了在 JavaScript 1.2 中引入的新特性的同时实现了平台独立。

当 Netscape 将它的源代码作为 Mozilla 项目公布于众时,本来计划 JavaScript 1.4 将会嵌入到 Netscape Navigator 5.0 中。然而,一个冒进的决定 - 要完全从头重新设计 Netscape 的代码,破坏了这个工作。JavaScript 1.4 仅仅作为一个 Netscape Enterprise Server 的服务器端脚本语言发布,以后也没有被放入浏览器中。

如今,所有主流的 Web 浏览器都遵守 ECMA-262 第三版。

下面的表格列出了大部分流行的 Web 浏览器中的 ECMAScript 支持:

浏览器	DOM 兼容性
Netscape Navigator 2.0	-
Netscape Navigator 3.0	-
Netscape Navigator 4.0 - 4.05	-
Netscape Navigator 4.06 - 4.79	Edition 1
Netscape 6.0+ (Mozilla 0.6.0+)	Edition 3
Internet Explorer 3.0	-
Internet Explorer 4.0	-
Internet Explorer 5.0	Edition 1
Internet Explorer 5.5+	Edition 3
Opera 6.0 - 7.1	Edition 2
Opera 7.2+	Edition 3
Safari 1.0+/Konqueror ~ 2.0+	Edition 3

DOM

DOM(文档对象模型)是 HTML 和 XML 的应用程序接口(API)。DOM 将把整个页面规划成由节点层级构成的文档。HTML 或 XML 页面的每个部分都是一个节点的衍生物。请考虑下面的 HTML 页面:

<html>
  <head>
    <title>Sample Page</title>
  </head>
  <body>
    <p>hello world!</p>
  </body>
</html>

这段代码可以用 DOM 绘制成一个节点层次图:
在这里插入图片描述

DOM 节点层次图
DOM 通过创建树来表示文档,从而使开发者对文档的内容和结构具有空前的控制力。用 DOM API 可以轻松地删除、添加和替换节点。

1. 为什么 DOM 必不可少

自从 IE 4.0 和 Netscape Navigator 4.0 开始支持不同形态的动态 HTML(DHTML),开发者首次能够在不重载网页的情况下修改它的外观和内容。这是 Web 技术的一大飞跃,不过也带来了巨大的问题。Netscape 和微软各自开发自己的 DHTML,从而结束了 Web 开发者只编写一个 HTML 页面就可以在所有浏览器中访问的时期。

业界决定必须要做点什么以保持 Web 的跨平台特性,他们担心如果放任 Netscape 和微软公司这样做,Web 必将分化为两个独立的部分,每一部分只适用于特定的浏览器。因此,负责指定 Web 通信标准的团体 W3C(World Wide Web Consortium)就开始制定 DOM。

2. DOM 的各个 level

DOM Level 1 是 W3C 于 1998 年 10 月提出的。它由两个模块组成,即 DOM Core 和 DOM HTML。前者提供了基于 XML 的文档的结构图,以便访问和操作文档的任意部分;后者添加了一些 HTML 专用的对象和方法,从而扩展了 DOM Core。

注意,DOM 不是 JavaScript 专有的,事实上许多其他语言都实现了它。不过,Web 浏览器中的 DOM 已经用 ECMAScript 实现了,现在是 JavaScript 语言的一个很大组成部分。

DOM Level 1 只是一个目标,即规划文档的结构,DOM Level 2 的目标就广泛多了。对原始 DOM 的扩展添加了对鼠标和用户界面事件(DHTML 对此有丰富的支持)、范围、遍历(重复执行 DOM 文档的方法)的支持,并通过对象接口添加了对 CSS(层叠样式表)的支持。由 Level 1 引入的原始 DOM Core 也加入了对 XML 命名空间的支持。

DOM Level 2 引入了几种 DOM 新模块,用于处理新的接口类型:

DOM 视图 - 描述跟踪文档的各种视图(即 CSS 样式化之前和 CSS 样式化之后的文档)
DOM 事件 - 描述事件的接口
DOM 样式 - 描述处理基于 CSS 样式的接口
DOM 遍历和范围 - 描述遍历和操作文档树的接口
DOM Level 3 引入了以统一的方式载入和保持文档的方法(包含在新模块 DOM Load and Save)以及验证文档(DOM Validation)的方法,从而进一步扩展了 DOM。在 Level 3 中,DOM Core 被扩展为支持所有的 XML 1.0 特性,包括 XML Infoset、XPath 和 XML Base。

在学习 DOM 时,可能会遇到有人引用 DOM Level 0。注意,根本没有 DOM Level 0 这个标准,它只是 DOM 的一个历史参考点(DOM Level 0 指的是 IE 4.0 和 Netscape Navigator 4.0 中支持的原始 DHTML)。

3. 其他 DOM

除了 DOM Core 和 DOM HTML 外,还有其他几种语言发布了自己的 DOM 标准。这些语言都是基于 XML 的,每种 DOM 都给对应语言添加了特有的方法和接口:

可缩放矢量语言(SVG)1.0
数字标记语言(MathML)1.0
同步多媒体集成语言(SMIL)
注释:如果希望学习更多相关内容,请访问 w3school 的 SMIL 教程 和 SVG 教程。

此外,其他语言也开发了自己的 DOM 实现,如 Mozilla 的 XML 用户界面语言(XUL)。不过,只有上面列出的几种语言是 W3C 的推荐标准。

4. Web 浏览器中的 DOM 支持

DOM 在被 Web 浏览器开始实现之前就已经是一种标准了。IE 首次尝试 DOM 是在 5.0 版本中,不过其实直到 5.5 版本之后才具有真正的 DOM 支持,IE 5.5 实现了 DOM Level 1。从那时起,IE 就没有引入新的 DOM 功能。

Netscape 直到 Netscape 6(Mozilla 0.6.0)才引入 DOM 支持。目前,Mozilla 具有最好的 DOM 支持,实现了完整的 Level 1、几乎所有 Level 2 以及一部分 Level 3。(Mozilla 开发小组的目标是构造一个与标准 100% 兼容的浏览器,他们的工作得到了回报。)

Opera 直到 7.0 版本才加入 DOM 支持,还有 Safari 也实现了大部分 DOM Level 1。它们几乎都与 IE 5.5 处于同一水平,有些情况下,甚至超过了 IE 5.5。不过,就对 DOM 的支持而论,所有浏览器都远远落后于 Mozilla。下表列出了常用浏览器对 DOM 的支持。

浏览器	DOM 兼容性
Netscape Navigator 1.0 - 4.x	-
Netscape 6.0+ (Mozilla 0.6.0+)	Level 1、Level 2、Level 3(部分)
IE 2.0 - 4.x	-
IE 5.0	Level 1(最小)
IE 5.5+	Level 1(几乎全部)
Opera 1.0 - 6.0	-
Opera 7.0+	Level 1(几乎全部)、Level (部分)
Safari 1.0+/Konqueror ~ 2.0+	Level 1
注释:如果希望进一步地学习 DOM 的知识,请访问 w3school 的 HTML DOM 教程 和 XML DOM 教程。

BOM

IE 3.0 和 Netscape Navigator 3.0 提供了一种特性 - BOM(浏览器对象模型),可以对浏览器窗口进行访问和操作。使用 BOM,开发者可以移动窗口、改变状态栏中的文本以及执行其他与页面内容不直接相关的动作。使 BOM 独树一帜且又常常令人怀疑的地方在于,它只是 JavaScript 的一个部分,没有任何相关的标准。

BOM 主要处理浏览器窗口和框架,不过通常浏览器特定的 JavaScript 扩展都被看做 BOM 的一部分。这些扩展包括:

弹出新的浏览器窗口
移动、关闭浏览器窗口以及调整窗口大小
提供 Web 浏览器详细信息的定位对象
提供用户屏幕分辨率详细信息的屏幕对象
对 cookie 的支持
IE 扩展了 BOM,加入了 ActiveXObject 类,可以通过 JavaScript 实例化 ActiveX 对象
由于没有相关的 BOM 标准,每种浏览器都有自己的 BOM 实现。有一些事实上的标准,如具有一个窗口对象和一个导航对象,不过每种浏览器可以为这些对象或其他对象定义自己的属性和方法。

ECMAScript

一、js的引入方式

  • 外部引入的js

    <script src=""></script>    //把外部引入放到结束body标签的上面
    
  • 嵌入到html中

    <script>                   //不写src属性
        js代码                   
    </script>
    

二、注释

  • 单行注释 //
  • 多行注释 alt+shift+a /* * **/

三、输出工具

  • ==console.log()==== 输出内容到控制台==
    console.log(“注意防护”);

  • ==alert()==弹出框
    window.alert(5 + 6);

  • ==document.write()==输出内容到body中,可以识别标签对
    document.write(5 + 6);

  • ==prompt()==输入框

    prompt("请输入一个整数",10);
    第一个参数:提示文本
    第二个参数:默认值
    获取到的数据均为字符串
    
  • 使用 innerHTML 写入 HTML 元素

    <p id="demo"></p>
    <script>
     document.getElementById("demo").innerHTML = 5 + 6;
    </script>
    

四、变量

存储数值的容器

命名规范:

  • 区分大小写
  • 以数字,字母,_,$组成,不能以数字开头
  • 不能用关键字(js里面已经用到的)或者保留字(js中以后会用到的)命名
  • 命名要有意义
  • 驼峰命名法:getDoumentById
  • 首字母大写法:Object
声明变量的关键字:
  • ==var==== 声明变量 ES5==

  • ==let==== 声明变量 ES6==

  • ==const==== 声明常量 ES6==

    可以使用 let 关键词声明拥有块作用域的变量。

    在相同的作用域,或在相同的块中,通过 let 重新声明一个 var 变量是不允许的

    在相同的作用域,或在相同的块中,通过 let 重新声明一个 let 变量是不允许的

    在相同的作用域,或在相同的块中,通过 var 重新声明一个 let 变量是不允许的

    块作用域内使用 const 声明的变量与 let 变量相似。

    块作用域内使用 const 声明的变量与 let 变量相似。

    如果我们将一个原始值赋给常量,我们就不能改变原始值

声明变量:
  • 声明单个变量

    var a;
    
  • 同时声明多个变量,要用,隔开。

    var b,c,d;
    

变量的默认值是undefined,变量声明但未赋值结果为undefined

初始化变量:(为变量赋值)
  • 先声明后赋值

    var num;
    num=100;
    
    var num1,num2,num3;
    num1=100;
    num2=200;
    num3=300;
    
  • 声明的同时进行赋值

    var num=100;
    
    var num1=100,num2=200,num3=300;
    
变量的更新:
var num=100;
num=200;
声明常量:

常量的值是不可变的。

const pi=3.1415926;

1.静态变量

静态变量也称作类变量,是在类之中,方法之外,以static关键字申明的变量,其独立在对象之外,有许多对象共享的变量。静态变量在对象产生之前产生,并长驻于内存,其在JVM关闭时销毁。

2.成员变量

成员变量也称作实例变量、属性, 申明在类之中,方法之外的变量,随对象销毁而销毁。

3.局部变量

在方法或语句块中申明的变量,生命周期只在定义的{}之中,不能跨方法或语句块使用。

生命周期由长到短分别为:

静态变量——>成员变量——>局部变量

五、数据类型

按照数据在内存中的存储位置,分为两种,初始数据类型和引用数据类型

typeof 运算符返回变量或表达式的类型

JavaScript共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。

JavaScript BigInt 变量用于存储太大而无法用普通 JavaScript 数字表示的 大整数值。

  • 其中 Symbol 和 BigInt 是ES6 中新增的数据类型:

    • Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。
    • BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。

这些数据可以分为原始数据类型引用数据类型

  • 栈:原始数据类型(Undefined、Null、Boolean、Number、String)

    • number:NaN Infinity
    • string
    • boolean
    • null
    • undefined
    • symbol static Symbol Symbol.prototype
    • bigint
  • 堆:引用数据类型(对象、数组和函数)

    • object:普通对象 数组对象 正则对象 日期对象 Math数学函数对象 JSON对象 Set Map …
    • function 普通函数 箭头函数 构造函数 生成器函数 匿名函数 自调用函数
  • 两种类型的区别在于存储位置的不同:

    • 原始数据类型直接存储在栈(stack)中的简单数据段占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
    • 引用数据类型存储在堆(heap)中的对象占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
  • 堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中:

    • 在数据结构中,栈中数据的存取方式为先进后出
    • 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。 在操作系统中,内存被分为栈区和堆区:
    • 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
    • 堆区内存一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。
  • <补充>两个栈实现一个队列

    入队:直接向 stack1 中入栈。

    出队:将 stack1 中的所有元素出栈,依次入栈到 stack2 中,然后弹出 stack2 中的栈顶元素,接着把 stack2 中的所有元素出栈,依次压入 stack1 中。

    (1) 使用两个栈A,B,其中假定A负责push操作,B负责pop操作。使用一个变量back_elem来存储最后添加的元素。

    (2) 实现队列的push操作, 每次进行添加操作,都会相应得对栈A进行添加元素。并对back_elem赋值

    (3) 实现队列的pop操作,每次进行删除操作,因为栈B负责pop操作,

数据类型检测

typeof () 对于基本数据类型没问题,遇到引用数据类型就不管用

instanceof( )只能判断引用数据类型,不能判断基本数据类型

constructor 几乎可以判断基本数据类型和引用数据类型;如果声明了一个构造函数,并把它的原型指向了Array

Object.prototype.tostring.call() 都可以

  • typeof 检测数据类型的逻辑运算符

    console.log(typeof 2); // number;
    console.log(typeof true); // boolean
    console.log(typeof 'str'); // string
    console.log(typeof function(){}); // function
     console.log(typeof undefined); // undefined
    
    console.log(typeof []);              // object  
    console.log(typeof {});              // object
    console.log(typeof null);            // object
    其中数组、对象、null都会被判断为object,其他判断都正确。
    
  • instanceof 检测是否为类的实例;==instanceof==可以正确判断对象的类型其内部运行机制是判断在其原型链中能否找到该类型的原型

  • instanceof 操作符用于检测对象是否属于某个 class,同时,检测过程中也会将继承关系考虑在内。

  • 实现原理及实现:instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置

  • instanceof 的内部实现机制是:通过判断对象的原型链上是否能找到对象的 prototype,来确定 instanceof 返回值

    • 原型(prototype): 函数的一个属性,是一个对象
      原型链(proto):Object对象的一个属性,也是一个Object对象。
      对象的__proto__保存着该对象构造函数的prototype
  • 基于上述概念,instanceof运算符的本质就是检查目标对象是被哪个方法构造的,因为存在继承关系,所以是在整个原型链上查找。也就是检测该对象是什么类型的。

    JS中的class是function的语法糖,所以上述概念依然适用。

    console.log(2 instanceof Number); // false
    console.log(true instanceof Boolean); // false
    console.log('str' instanceof String); // false
    
    console.log([] instanceof Array);                    // true
    console.log(function(){} instanceof Function);       // true
    console.log({} instanceof Object);                   // true
    可以看到,instanceof只能正确判断引用数据类型,而不能判断基本数据类型。instanceof 运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
    
    原理:
    function myInstanceof(left, right) {
      // 获取对象的原型
      let proto = Object.getPrototypeOf(left)
      // 获取构造函数的 prototype 对象
      let prototype = right.prototype; 
     
      // 判断构造函数的 prototype 对象是否在对象的原型链上
      while (true) {
        if (!proto) return false;
        if (proto === prototype) return true;
        // 如果没有找到,就继续从其原型上找,Object.getPrototypeOf方法用来获取指定对象的原型
        proto = Object.getPrototypeOf(proto);
      }
    }
    

    constructor 检测构造函数

    > *   console.log((2).constructor === Number); // true
    >     console.log((true).constructor === Boolean); // true
    >     console.log(('str').constructor === String); // true
    >     console.log((\[]).constructor === Array); // true
    >     console.log((function() {}).constructor === Function); // true
    >     console.log(({}).constructor === Object); // true
    >     constructor有两个作用,一是判断数据的类型,二是对象实例通过 constrcutor 对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了:
    >     function Fn(){};
    >     Fn.prototype = new Array();
    >     var f = new Fn();
    >     console.log(f.constructor===Fn);    // false
    >     console.log(f.constructor===Array); // true
    
    
    
  • Object.prototype.toString.call 检测数据类型;使用 Object 对象的原型方法 toString 来判断数据类型

    
    var a = Object.prototype.toString;
    console.log(a.call(2));
    console.log(a.call(true));
    console.log(a.call('str'));
    console.log(a.call([]));
    console.log(a.call(function(){}));
    console.log(a.call({}));
    console.log(a.call(undefined));
    console.log(a.call(null));
    同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?
    这是因为toString是Object的原型方法,而Array、function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串…),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object原型上的toString方法。
    

判断数组的方式有哪些

  • 通过Object.prototype.toString.call()做判断

    Object.prototype.toString.call(obj).slice(8,-1) === ‘Array’;

  • 通过原型链做判断

    obj.proto === Array.prototype;

  • 通过ES6的Array.isArray()做判断

    Array.isArrray(obj);

  • 通过instanceof做判断

    obj instanceof Array

  • 通过Array.prototype.isPrototypeOf

    Array.prototype.isPrototypeOf(obj)

初始数据类型(存在栈区)

类型typeof的结果
undefinedundefined变量声明未赋值的时候为undefinedundefined
nullnull相当于一个占位符object
string字符串型用单引号或者双引号包裹的string
number整数,浮点数,十进制,十六进制(0x),八进制(0,0o),二进制(0b),最大值,最小值,科学计数法,NaN(不是一个数)。number
booleanture,falseboolean
symbol表示独一无二的值
string型:
  • 单双引号效力相同

  • 单双引号要成对存在

  • 单双引号相互嵌套

  • 由于字符串必须由引号包围, 使用*\ 转义字符*

    \’单引号
    \""双引号
    length 属性返回字符串的长度\\\反斜杠
  • length 属性返回字符串的长度

  • indexOf() 方法返回字符串中指定文本首次出现的索引(位置)

  • lastIndexOf() 方法返回指定文本在字符串中最后一次出现的索引

  • search() 方法搜索特定值的字符串,并返回匹配的位置

  • slice() 提取字符串的某个部分并在新字符串中返回被提取的部分

  • substring() 类似于 slice()。不同之处在于 substring() 无法接受负的索引。

  • substr() 类似于 slice()。不同之处在于第二个参数规定被提取部分的长度

  • replace() 方法用另一个值替换在字符串中指定的值

  • 通过 toUpperCase() 把字符串转换为大写,

    通过 toLowerCase() 把字符串转换为小写

  • concat() 连接两个或多个字符串

  • trim() 方法删除字符串两端的空白符

  • charAt() 方法返回字符串中指定下标(位置)的字符串

  • charCodeAt() 方法返回字符串中指定索引的字符 unicode 编码

  • 可以通过 split() 将字符串转换为数组

  • match() 方法根据正则表达式在字符串中搜索匹配项,并将匹配项作为 Array 对象返回。

  • 如果字符串包含指定值,includes() 方法返回 true

  • 如果字符串以指定值开头,则 startsWith() 方法返回 true,否则返回 false

  • 如果字符串以指定值结尾,则 endsWith() 方法返回 true,否则返回 false

Number数字方法:
  • toString() 方法将数字作为字符串返回

  • toExponential() 返回字符串,其中的数字四舍五入并使用指数表示法书写

  • toFixed() 返回一个字符串,其中的数字带有指定位数的小数部分。

  • toPrecision() 返回一个字符串,其中包含指定长度的数字

  • valueOf() 以数字形式返回数字。

  • Number() 方法可用于将 JavaScript 变量转换为数字

  • Number() 也可以将日期转换为数字。Date() 方法返回自 1970 年 1 月 1 日以来的毫秒数。

  • parseInt() 解析字符串并返回整数。允许有空格。仅返回第一个数字:

  • parseFloat() 解析字符串并返回数字。允许有空格。仅返回第一个数字

  • 如果参数是整数,则 Number.isInteger() 方法返回 true

  • 安全整数指的是可以被精确表示为双精度浮点数的整数。

    如果参数是安全整数,则 Number.isSafeInteger() 方法返回 true

  • Number.parseFloat() 解析字符串并返回数字。允许有空格。仅返回第一个数字:

  • Number.parseInt() 解析字符串并返回整数。

    允许有空格。仅返回第一个数字

  • Number.EPSILON 是大于 1 的最小浮点数与 1 之差。

  • Number.MAX_VALUE 是 JavaScript 中表示最大可能数字的常量。

  • Number.MIN_VALUE 是 JavaScript 中表示最小可能数字的常量。

  • Number.MAX_SAFE_INTEGER 表示 JavaScript 中的最大安全整数。

  • Number.MIN_SAFE_INTEGER 表示 JavaScript 中的最小安全整数。

Symbol 是构造函数吗?

Symbol 是基本数据类型,它并不是构造函数,因为它不支持 new Symbol() 语法。我们直接使用Symbol() 即可。

let an = Symbol("An");

let an1 = new Symbol("An"); 
// Uncaught TypeError: Symbol is not a constructor

但是,Symbol() 可以获取到它的 constructor 属性

Symbol("An").constructor; 
// ƒ Symbol() { [native code] }

这个 constructor 实际上是 Symbol 原型上的,即

Symbol.prototype.constructor; 
// ƒ Symbol() { [native code] }

对于 Symbol,你还需要了解以下知识点:

Symbol() 返回的 symbol 值是唯一
Symbol("An") === Symbol("An"); 
// false

可以通过 Symbol.for(key) 获取全局唯一的 symbol
Symbol.for('An') === Symbol.for("An"); // true

它从运行时的 symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中。

Symbol.iterator :返回一个对象的迭代器
// 实现可迭代协议,使迭代器可迭代:Symbol.iterator
function createIterator(items) {
    let i = 0
    return {
        next: function () {
            let done = (i >= items.length)
            let value = !done ? items[i++] : undefined
            return {
                done: done,
                value: value
            }
        },
        [Symbol.iterator]: function () {
        	return this
    	}
    }
}
const iterator = createIterator([1, 2, 3]);
[...iterator];		// [1, 2, 3]

Symbol.toPrimitive:将对象转换成基本数据类型
// Symbol.toPrimitive 来实现拆箱操作(ES6 之后)
let obj = {
    valueOf: () => {console.log("valueOf"); return {}},
    toString: () => {console.log("toString"); return {}}
}
obj[Symbol.toPrimitive] = () => {console.log("toPrimitive"); return "hello"}
console.log(obj + "") 
// toPrimitive
// hello

Symbol.toStringTag:用于设置对象的默认描述字符串值
// Symbol.toStringTag 代替 [[class]] 属性(ES5开始)
let o = { [Symbol.toStringTag]: "MyObject" }

console.log(o + ""); 
// [object MyObject]
NULL

null 特指对象的值未设置,它是 JS 基本类型 之一,在布尔运算中被认为是falsy

null 表示 “什么都没有”。

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

用 typeof 检测 null 返回是object。

可以直接通过val === null来判断

let val = null
console.log(val === null) // true
console.log(Number(val) === 0) // true
console.log(!val) // true

console.log(typeof(val)) // object
console.log(isNaN(val)) // false
typeof null 的结果是什么,为什么?

typeof null 的结果是Object

在 JavaScript 第一个版本中,所有值都存储在 32 位的单元中,每个单元包含一个小的 类型标签(1-3 bits) 以及当前要存储值的真实数据。类型标签存储在每个单元的低位中,共有五种数据类型:

000: object   - 当前存储的数据指向一个对象。
  1: int      - 当前存储的数据是一个 31 位的有符号整数。
010: double   - 当前存储的数据指向一个双精度的浮点数。
100: string   - 当前存储的数据指向一个字符串。
110: boolean  - 当前存储的数据是布尔值。

如果最低位是 1,则类型标签标志位的长度只有一位;如果最低位是 0,则类型标签标志位的长度占三位,为存储其他四种数据类型提供了额外两个 bit 的长度。

有两种特殊数据类型:

  • undefined的值是 (-2)30(一个超出整数范围的数字);
  • null 的值是机器码 NULL 指针(null 指针的值全是 0)

那也就是说null的类型标签也是000,和Object的类型标签一样,所以会被判定为Object。

undefined

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

typeof 一个没有值的变量会返回 undefined。
var person;                  // 值为 undefined(空), 类型是undefined
let val = undefined
console.log(val === undefined) // true
console.log(typeof(val) === 'undefined') // true
console.log(!val) // true

console.log(Number(val)) // NaN
console.log(isNaN(val)) // true
undefined 和 null 的区别

首先 Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null。

undefined 代表的含义是未定义,null 代表的含义是空对象

一般变量声明了但还没有定义的时候会返回 undefined,

null主要用于赋值给一些可能会返回对象的变量,作为初始化。

undefined 在 JavaScript 中不是一个保留字,这意味着可以使用 undefined 来作为一个变量名,但是这样的做法是非常危险的,它会影响对 undefined 值的判断。我们可以通过一些方法获得安全的 undefined 值,比如说 void 0。

当对这两种类型使用 typeof 进行判断时,Null 类型化会返回 “object”,这是一个历史遗留的问题。

当使用双等号对两种类型的值进行比较时会返回 true,

使用三个等号时会返回 false。

null 和 undefined 的值相等,但类型不等:

(1)undefined:是所有没有赋值变量的默认值,自动赋值

(2==)null:主动释放一个变量引用的对象,表示一个变量不再指向任何对象地址。==

typeof undefined             // undefined
typeof null                  // object
null == undefined            // true
null === undefined           // false

2、何时使用null?

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

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

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

不同点:

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

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

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

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

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

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

4、延伸——垃圾回收站

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

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

NaN:JavaScript中的数字类型是所有数字值的集合,包括“非数字”,正无穷大和负无穷大。

NaN 即非数值(Not a Number),NaN 属性用于引用特殊的非数字值,该属性指定的并不是不合法的数字。

NaN 属性 与 Number.Nan 属性相同。

提示: 请使用 isNaN() 来判断一个值是否是数字。原因是 NaN 与所有值都不相等,包括它自己。

let val = NaN
console.log(isNaN(val)) // true

console.log(val === NaN) // false
console.log(Number(val)) // NaN
console.log(typeof(val)) // number
空值的判断
let val = ''
console.log(!val) // true
console.log(typeof(val)) // string
console.log(isNaN(val)) // false
常见假值的判断

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

引用数据类型 object(存在堆区)

是属性与方法的集合,object对象,array数组,function函数。

//对象
var obj={};       //object
//数组
var obj1=[];      //object
Array.isArray(fruits);     // 返回 true  是否为数组
//函数
var obj2=function(){};       //function
Array数组方法:
  • toString() 把数组转换为数组值(逗号分隔)的字符串

  • join() 方法也可将所有数组元素结合为一个字符串。

    它的行为类似 toString(),但是您还可以规定分隔符

  • 在处理数组时,删除元素和添加新元素是很简单的。Popping 和 Pushing 指的是:从数组弹出项目,或向数组推入项目。

  • pop() 方法从数组中删除最后一个元素:

  • push() 方法(在数组结尾处)向数组添加一个新的元素

  • shift() 方法会删除首个数组元素,并把所有其他元素“位移”到更低的索引

  • unshift() 方法(在开头)向数组添加新元素,并“反向位移”旧元素:

  • 通过使用它们的索引号来访问数组元素

  • length 属性提供了向数组追加新元素的简易方法

  • 既然 JavaScript 数组属于对象,其中的元素就可以使用 JavaScript delete 运算符来删除

  • 使用 delete 会在数组留下未定义的空洞。请使用 pop()shift() 取而代之。

  • splice() 方法可用于向数组添加新项

  • 使用 splice() 在数组中不留“空洞”的情况下移除元素

  • slice() 方法用数组的某个片段切出新数组

  • concat() 方法通过合并(连接)现有数组来创建一个新数组

  • sort() 方法以字母顺序对数组进行排序,对数值排序时会产生不正确的结果。

  • reverse() 方法反转数组中的元素

  • function(a, b){return a-b}比较函数的目的是定义另一种排序顺序 对数值字符串

  • Math.max.apply 来查找数组中的最高值

  • Math.min.apply 来查找数组中的最低值

  • forEach() 方法为每个数组元素调用一次函数(回调函数)

  • map() 方法通过对每个数组元素执行函数来创建新数组。

  • filter() 方法创建一个包含通过测试的数组元素的新数组。

  • reduce() 方法在每个数组元素上运行函数,以生成(减少它)单个值。

  • reduceRight() 方法在每个数组元素上运行函数,以生成(减少它)单个值。

  • every() 方法检查所有数组值是否通过测试。

  • indexOf() 方法在数组中搜索元素值并返回其位置。

  • Array.lastIndexOf()Array.indexOf() 类似,但是从数组结尾开始搜索。

  • findIndex() 方法返回通过测试函数的第一个数组元素的索引。

日期数据

Date 对象由新的 Date() 构造函数创建。

  • new Date() 用当前日期和时间创建新的日期对象

  • new Date(year, month, day, hours, minutes, seconds, milliseconds)用指定日期和时间创建新的日期对象。

    • 7个数字分别指定年、月、日、小时、分钟、秒和毫秒(按此顺序)

      不能省略月份。如果只提供一个参数,则将其视为毫秒。

      一位和两位数年份将被解释为 19xx 年

  • new Date(dateString) 从日期字符串创建一个新的日期对象

  • new Date(milliseconds) 创建一个零时加毫秒的新日期对象

  • 日期格式

    • ISO 8601 语法 (YYYY-MM-DD) 也是首选的 JavaScript 日期格式
    • 短日期通常使用 “MM/DD/YYYY” 这样的语法
    • 长日期通常以 “MMM DD YYYY” 这样的语法来写
    • JavaScript 接受“完整 JavaScript 格式”的日期字符串
  • 日期获取方法

    • getTime() 方法返回自 1970 年 1 月 1 日以来的毫秒数
    • getFullYear() 方法以四位数字形式返回日期年份
    • getMonth() 以数字(0-11)返回日期的月份
    • getDate() 方法以数字(1-31)返回日期的日
    • getHours() 方法以数字(0-23)返回日期的小时数
    • getMinutes() 方法以数字(0-59)返回日期的分钟数
    • getSeconds() 方法以数字(0-59)返回日期的秒数
    • getMilliseconds() 方法以数字(0-999)返回日期的毫秒数
    • getDay() 方法以数字(0-6)返回日期的星期名(weekday)
  • 日期设置方法

    • setFullYear() 方法设置日期对象的年份
    • setFullYear() 方法可以选择设置月和日
    • setMonth() 方法设置日期对象的月份(0-11)
    • setDate() 方法设置日期对象的日(1-31):
    • setHours() 方法设置日期对象的小时(0-23)
    • setMinutes() 方法设置日期对象的分钟(0-59)
    • setSeconds() 方法设置日期对象的秒数(0-59)

new、this、class、函数

this 与 new

new 关键字创建的对象实际上是对新对象 this 的不断赋值,并将 __proto__ 指向类的 prototype 所指向的对象

在函数调用前增加 new,相当于把 SuperType 当成一个构造函数(虽然它仅仅只是个函数),然后创建一个 {} 对象并把 SuperType 中的 this 指向那个对象,以便可以通过类似 this.mouse 的形式去设置一些东西,然后把这个对象返回。

具体来讲,只要在函数调用前加上 new 操作符,你就可以把任何函数当做一个类的构造函数来用。

加 new

在上例中,我们可以看到:在构造函数内定义的 私有变量或方法 ,以及类定义的 静态公有属性及方法 ,在 new 的实例对象中都将 无法访问

不加 new

如果你调用 SuperType()没有new,其中的 this 会指向某个全局且无用的东西(比如,window 或者 undefined),因此我们的代码会崩溃,或者做一些像设置 window.mouse 之类的傻事。

this 关键字
  • 面向对象语言中 this 表示当前对象的一个引用。

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

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

对于箭头函数,使用 new 会报错🔴

复制代码const Bottle = () => {console.log('Hello, AnGe')};
new Bottle(); // Uncaught TypeError: Bottle is not a constructor

这个行为是遵循箭头函数的设计而刻意为之的。箭头函数的一个附带作用是它没有自己的 this 值 —— this 解析自离得最近的常规函数:

复制代码function AnGe() {
    this.name = 'AnGe'
    return () => {console.log('Hello, ' + this.name)};
}
let anGe = new AnGe();
console.log(anGe()); // Hello, AnGe

所以**箭头函数没有自己的 this。**但这意味着它作为构造函数是完全无用的!

总结:箭头函数

  • this 指向定义时的环境。

  • 不可 new 实例化

  • this 不可变。

  • 没有 arguments 对象

    允许一个使用 new 调用的函数返回另一个对象以 覆盖 new 的返回值

六、运算符

算术运算符

+ - * / % ++ --

  • - * / %

    • 操作数都是数字,按照四则运算规则
    • 如果一个是数字,另一个是字符串,尝试将字符串转换为数字,成功会按照四则运算规则,失败会返回NaN
  • +:

  1. 如果操作数都是数字,做加法运算
  2. 如果操作数中只要有一个是字符串,做拼接运算
  3. 数字与除字符串以外类型相加: 将其他类型转化为数字后算术相加,无法转化则结果为NaN
    • true 转化为1
    • false、null转化为0
    • undefined 无法转化
  4. NaN与除字符串以外类型相加结果都为NaN
  • -:

    • 数字和字符串相减 :
      • 字符串全部由数字组成,将字符串转化为数字,再相减
      • 字符串不能转化为数字,结束是 NaN
      • null转化为0 undefined转化为NaN true为1 false为0
  • 加减法做数字与字符串的转换:

    • 数字转化为字符串: num + ""
    • 字符串转化为数字: num - 0
  • *:

  1. 数字与字符串运算:
    • 将字符串尝试着转化为数字,进行运算
    • 字符串不能转化为数字,结果是 NaN
  2. null转化为0 true为1 false为0 空字符串转为0
  3. Undefined乘所有数据类型的都为NaN
  • /
  1. 字符串类型 数字类型与 null 相除 结果为 Infinity
  2. 字符串类型、数字类型 null与 Undefined 相除 结果为 NaN
  3. 字符串类型 数字类型 null与 字符串类型、数字类型 null相除进行相应转换做除法运算
    • 字符串不能转为数字则结果为NaN
    • 空字符串转为0
  • %:
  1. Undefined 与所有数据类型的 取余 都为NaN
  2. 其余数据类型先进行转换,能转为数字则进行取余运算,否则为NaN
  • ++var var++:
  1. 相同点:自增
  2. 不同点:++在前要先自增,再参与运算。++在后要先参与运算,最后做自增。
a++;
a+4;
  • ** Math.pow(x,y) 幂运算

    var x = 5;
    var z = x ** 2;          // 结果是 25
    var x = 5;
    var z = Math.pow(x,2);   // 结果是 25
    
关系运算符(比较运算符)

比较运算符得到的结果都是boolean值。

> < >= <= == != === !==

  1. 操作数都是数字 正数>0>负数
  2. 数字与字符串比较,尝试将字符串转换为数字,如果能够转换成功按照数字的规则进行比较,转换不成功就会返回false。数字型字符串可以转换为数字。
  3. 数字与布尔值比较,true转换为1,false转换为0。
  4. 操作数都是字符串,需要按照ASCII码表进行按位比较。
  5. NaN与任意数据比较,结果为false。
  6. ==比较的是值相等,===比较的是值和数据类型都相等
  7. undefined==null是true
  8. 0==""是ture
  9. 0==" "是true
  10. 0==undefined是false
  11. 使用双等号(==)进行相等判断时,如果两边的类型不一致,则会进行强制类型转化后再进行比较。
  12. 使用三等号(===)进行相等判断时,如果两边的类型不一致时,不会做强制类型准换,直接返回 false。
  13. 使用 Object.is 来进行相等判断时,一般情况下和三等号的判断相同,它处理了一些特殊的情况,比如 -0 和 +0 不再相等,两个 NaN 是相等的。
逻辑运算符

0 “” false undefined null NaN 这六种为假值。

短路原则:找到符合条件的,后面的代码不执行。

真值表

ABA&&BA||B!A
truetruetruetruefalse
truefalsefalsetruefalse
falsetruefalsetruetrue
falsefalsefalsefalsetrue
  • &&与:

    • 同真为真(条件判断)
    • 期望寻找一个假值,如果能找到假值就输出假值,找不到假值就输出最后一个真值,短路原则
  • ||或:

    • 同假为假
    • 期望寻找一个真值,如果能找到真值就输出真值,找不到就输出最后一个假值,短路原则
  • !非:

    • 取反
    • 最终输出结果为boolean值
赋值运算符

= += -= = /= %= <<= >>= &= ^= |= **=

一元运算符
  1. new
  2. typeof
  3. delete
  4. instanceof
三元运算符
var variable=条件?1:2;
//条件为真,将值1的值赋给variable,否则将值2的值赋给variable
特殊运算符

,:一次性声明多个变量

():提升运算优先级

运算符的优先级
  • 乘法(*)和除法(%)比加法(+)和减法(-)拥有更高的优先级
  • 通过使用括号来改变优先级
  • 当多个运算拥有相同的优先级时(比如加法和减法),对它们的计算是从左向右的
  • JavaScript 算数 (w3school.com.cn)

七、流程控制

指通过规定的语句让程序代码有条件的按照一定的方式执行。

结构

  • 顺序结构
  • 选择结构(分支结构)
  • 循环结构

选择结构

根据给定的条件有选择的执行相应的语句。 双等于

if
if(条件1){
    满足条件1时执行的代码;
}else if(条件2){
    满足条件2时执行的代码;
}else{
    以上条件都不满足时执行的代码;
}            满足一定条件的时候用分支结构
  • 单分支
  • 双分支
  • 多分支
  • 嵌套分支
switch
switch(变量){
    case1:满足值1时执行的语句;break;
    case2:满足值2时执行的语句;break;
    case3:满足值3时执行的语句;break;
    default:以上条件都不满足时执行的语句;
}
//case后的值与变量能够取到的值符合全等
if与switch的选择:
  • 如果做范围判断用if,如果判断单个值用switch
  • 条件不可重复

循环结构

满足一定的条件下重复不断的执行一定的代码。

for
//初始条件;终止条件;步进值
for(var i=0;i<10;i++){
    循环体;
}
while
while(条件){
      循环体;
      }
do while
do{
    循环体;
}while(条件)
for while do while区别
  • 如果知道循环的次数,优先考虑for循环。如果不知道循环的次数,只是知道循环的条件,只能用while和do while。
  • whiledo while:如果初始条件不成立,while一次都不执行,do while要执行一次。
循环跳转语句(终止离它最近的循环)
  • continue:终止本次循环
  • break:终止整个循环

八、数组

用来存储一组相同或相关的数据。

声明与赋值

  • 隐式创建[]
var arr=[1,2,3,'a',true];
  • 构造函数创建new Array
var arr=new Array(1,2,3,'a',true);

给new Array中添加一个值并且是数字,代表数组的长度。new Array(3)

数组的访问

  • 要通过下标去访问,arr[0],数组的下标从0开始,下标结束arr.length-1

  • 利用arr.length来访问数组的长度。

  • 数组中的数据可以是任意数据类型

  • 数组元素的默认值是undefined

  • 数组可以越界访问,访问结果为undefined

遍历

挨着访问,一个一个访问。

for
for(var i=0;i<arr.length;i++){
    console.log(arr[i]);
}
for in
for(var i in arr){
    i;   //代表下标
    arr[i]; //代表元素
}
for of(es6)
for(var i of arr){
    i; //代表元素
}

二维数组

概念

数组中的每一个子元素都是数组。

声明与赋值
var arr=[[1,2,3],["a","b","c"],[6,5,7]];
遍历
for(var i=0;i<arr.length;i++){
    for(var j=0;j<arr[i].length;j++){
        console.log(arr[i][j]);
    }
}

九、函数

什么是函数

将完成某一特定功能的代码封装起来,并且可以重复调用的代码块。

优点
  1. 可以重复调用
  2. 参数的使用可以使函数更加灵活
  3. 利于维护与修改

函数声明的方式

function关键字
function fnName(形参,....){
    //函数体
    return
}
字面量定义(匿名函数)
var 变量=function(形参,.....){
    函数体
    return
}
实例化构造函数
var 变量=new Function(形参,.....,"函数体");  //函数体一定要加引号 

函数调用的方式

  • 函数名();
  • 变量名();
  • 匿名函数:
function fun1(){}
fun1();

var fun2=function(){}
fun2();

(function(形参){
    函数体
})()

注意事项

  • 利用==function==关键字声明的函数,可以在声明之前与声明之后调用。
  • 利用字面量方式和构造函数方式声明的函数只能在声明之后进行调用
  • 同名函数可以声明多个,但是后面的函数会将前面的进行覆盖。
  • 一个页面可以有多个script,并且能够相互起作用,但是后面的function可以访问前面的function,前面的function不可以访问后面的function,这是因为代码加载的顺序是由上到下的。

参数

可以动态的改变函数变量的类型值,使同一个函数实现不同的效果。

参数的类型
  • 形参:在定义函数时,括号中的变量叫做形参。
  • 实参:在调用函数时,括号中的值代表实参,作用是给形参传值。
参数的数据类型

参数可以是任意的数据类型。

参数的传递与个数
  • 实参个数 = 形参个数:按照从左到右的顺序一一对应

  • 实参个数 < 形参个性:多余的形参的值是undefined

  • 实参个数 > 形参个数:全部的参数会由arguments对象去接受

    • arguments
      • 类似数组但并不是数组
      • 默认存在于函数内部,并且也只能在函数内部去使用
      • 有下标,有长度,可以遍历
给参数赋默认值:
  • 分支结构
if(type==undefined){
    type=">";
}else{
    type=type;
}
  • 三元表达式
type=(type==undefined)?">":type;
  • 逻辑或
type=type||">";

函数返回值

在函数调用的地方返回一个特定的值,使我们可以对函数的结果进行处理。

注意
  • 函数的返回值与调试工具的输出无关
  • 如果不设置函数的返回值,默认值为undefined
  • 返回值的类型可以是任意数据类型
  • 一个函数可以有多个return分支,但只执行一个return分支,并且只能有一个返回值
function aa(a,b,c){
    return a,b,c;
}
console.log(aa(1,2,3));  //此时弹出3,只会返回最后一个值
功能
  • 将函数的运行结果返回
  • 终止并跳出函数
function aa(){
    return;
    alert(1);
}

aa();  //此时调用不会弹出1


function aa(){
    alert(1);
}
//首先调用函数aa()弹出1  其次输出返回值undefined
console.log(aa());

回调函数

把一个函数当作参数传递给另一个函数,并且会在另一个函数中进行调用。把被当作参数的函数叫做回调函数。

  • 函数名
console.log(filterArr(arr,isOdd));
  • 匿名函数
console.log(filterArr(arr,function(num){return num%2==0?true:false;}));

作用域

一段代码起作用的范围。

  • 全局作用域

    • 在函数外部用var声明的变量
    • 不用var声明的变量
  • 局部作用域

    • 在函数 内部用var声明的变量
    • 形参
作用域链

访问变量值时遵循的一条规则。由内向外的去访问,由本作用域开始直到逐级向上回溯直到全局环境,只能由内向外访问,不能由外向内访问。

内置顶层函数

内置

ECMAscript 自带的函数,ECMAscript将我们常用的一些功能封装起来,用户不需要知道其实现原理而直接使用。

顶层

指函数的作用范围,作用范围为全局。

  • Number()任意数据类型转换为数字,转换成功为数字,不成功为NaN

    • 布尔值:true为1,false为0
    console.log(Number(true));  //1
    console.log(Number(false));  //0
    
    • 数值:转换为本身,将无意义的前导零与后导零去掉
    console.log(Number(12.3));  //12.3
    console.log(Number(000011));  //八进制 9
    console.log(Number(12.3000)); //12.3
    
    • null:0
    console.log(Number(null)); //0
    
    • 字符串

      • 字符串中只有数字,则转换为数字(十进制),会忽略前导0和后导0
      console.log(Number("123")); //123
      console.log(Number("123ABC")); //转换不成功 NaN
      
      • 规范的浮点数,则转换为浮点数,会忽略前导0和后导0
      console.log(Number("12.3.3")); //转换不成功 NaN
      
      • 空字符串,转换为0
      console.log(Number("")); //0
      console.log(Number("  ")); //0
      
  • String()任意数据类型转换为字符串

    • 如果是null和undefined,转换为字符串"null"“undefined”
    console.log(String(null));// "null"
    
    • 如果是数值类型,转换为本身的字符串
    console.log(String(123)); //"123"
    console.log(typeof String(123));  //string
    
    • 如果是布尔类型,true转换为"true",false转换为"false"
    console.log(String(true)); //"true"
    
  • Boolean()任意数据类型转换为布尔值

    • 转换结果为假的6中情况:""(空串) null undefined 0 false NaN
    console.log(Boolean(null));//false
    
    • 其余情况都为真
    console.log(Boolean(123)); //true
    
  • parseInt()任意数据类型转换为整数 转换不成功是NaN

    • 如果一个字符串只包含数字,转换为十进制数,如果后面还包含字母,则转换到数字结束,字母不转换。
    console.log(parseInt("123")); //123
    console.log(parseInt("123abc")); //123
    console.log(parseInt("0b11"));  //0
    
    • 如果不是以数字空格+-开头的都转为为NaN
    console.log(parseInt("123abc")); //123
    console.log(parseInt("abc123")); //NaN
    console.log(parseInt("+123"));  //123
    console.log(parseInt("-123"));  //-123
    console.log(parseInt("    123"));  //123
    console.log(parseInt("!123"));  //NaN
    
    • 有两个参数时,第一个参数表示要转换的值,第二个参数表示几进制,返回值是一个十进制的数字。

      • **注意:**第一个参数从最高位开始计算,只要有一位数可以识别为第二个参数传入的进制,则可以实现转化
      • **注意:**第二个参数可以传入的值为 2-36
      console.log(parseInt(11,2));  //3
      console.log(parseInt(11,8));  //
      
  • parseFloat()任意数据类型转换为浮点数,转换不成功是NaN

    • 只有一个小数点起作用,其他无效
    console.log(parseFloat("12.3.3")); //12.3 隐式调用了Number()
    console.log(parseFloat(true));  //NaN
    console.log(parseFloat(undefined));  //NaN
    
    • 如果字符串是一个有效的整数,返回的是整数,不会返回浮点数
    console.log(parseFloat(123));//123
    console.log(parseFloat(0b11)); //3
    
    • 如果是字符串,则一个一个解析到数值结束,如果字符串不是以数字空格+-开头的都转为为NaN
    console.log(parseFloat("0b11"));//0
    console.log(parseFloat("123abc"));  //123
    console.log(parseFloat("abc123"));  //NaN
    console.log(parseFloat("-123"));  //-123
    console.log(parseFloat("    123"));  //123
    console.log(parseFloat("!123")); //NaN
    
  • isNaN()判断一个数据是否能转换为数值

    • 如果能够转换为数值返回false,不能返回true,相当于内部隐式调用了Number()
    console.log(isNaN(null));  //null可以转换为0,所以返回false
    console.log(isNaN("abc")); //true
    
  • eval()将传入的字符串当作js代码执行

var str = "(1+2)*3";
console.log(eval(str));      // 9
  • 避免在不必要的情况下使用 eval
    • 需要解析,速度慢
    • 安全性差:所执行的字符串容易被操控修改从而收到攻击
作用

数据类型转换

  • 强制数据类型转换
  • 隐使数据类型转换

十、对象

  • 一切皆对象,对象是无数属性与方法的集合
  • 类是对象的抽象,对象是类的具体化与实例化
  • 属性:用数据值来描述对象的状态
  • 方法:用函数来描述对象的功能

声明对象

隐式创建
var dl={
          name:"邓伦",
          age:28,
          height:184,
          "home":"石家庄",
          "TV":function(){
              return "香蜜沉沉烬如霜";
          }
      };
console.log(dl.name);
console.log(dl.age);
console.log(dl.height);
console.log(dl.home);
console.log(dl.TV());
实例化Object

相对于创建一个空对象

var dlrb=new Object();
dlrb.name="迪丽热巴";
dlrb.age=28;
dlrb.height=168;
dlrb.home="新疆";
dlrb.TV=function(){
     return "一千零一夜";
  }
console.log(dlrb.name);
console.log(dlrb.age);
console.log(dlrb.height);
console.log(dlrb.home);
console.log(dlrb.TV());
实例化自定义的构造函数
function Star(name,age,height,home){
            this.name=name;                 //谁实例化构造函数,this指向谁
            this.age=age;
            this.height=height;
            this.home=home;
            this.TV=function(TVname){
                return name+"出演电视剧"+TVname;
            }
        }
var dl1=new Star("邓伦",28,184,"石家庄");
var dlrb1=new Star("迪丽热巴",28,168,"新疆");
console.log(dl1);
console.log(dlrb1);
console.log(dl1.name);
console.log(dl1.TV("《加油,你是最棒的》"));
class

对象的基本操作

  • 对象.属性名=属性值
  • delete 对象.属性名
  • delete 对象.方法名
  • 销毁对象
对象=null;

重新赋值

  • 对象.属性名=新的属性值
  • 对象.方法名=新的方法
  • 属性

    • 对象.属性名
    • 对象[“属性名”]
  • 方法

    console.log(dl1.name);
    console.log(dlrb["name"]);
    console.log(dl1.TV("《香蜜沉沉烬如霜》"));
    console.log(dl1["TV"]("《一千零一夜》"));
                
    访问对象身上没有的属性返回undefined
    访问对象身上没有的方法会报错
    
对象的遍历

for in:

//键值对
//遍历键
for(var i in 对象){
    console.log(i);
}
//遍历值
for(var i in 对象){
    console.log(对象[i]);
}

Array对象

属性
  • length:数组中元素的个数
  • constructor:返回数组对象的构造函数(可以用来判断变量是否为数组)
console.log(arr.length);
console.log(arr.constructor);
方法
  • 添加与删除

    • push() 向数组的末尾添加一个或者多个元素 ★★★★★
    //会修改原数组
    //返回值:修改后的length值
    //可以追加多个
    var arr=[1,2,3,4];
    console.log(arr.push('a','b','c'));  //7
    console.log(arr);  //[1, 2, 3, 4, "a", "b", "c"]
    
    • unshift() 向数组的前面添加一个或者多个元素
    //会修改原数组
    //返回值:修改后的length值
    //可以追加多个
    var arr=[1,2,3,4];
    console.log(arr.unshift('x','y','x'));  //7
    console.log(arr);  //["x", "y", "x", 1, 2, 3, 4]
    
    • pop() 删除数组的最后一个元素
    //会修改原数组
    //返回值:被删除的数据
    //只能删除一个
    var arr=[1,2,3,4];
    console.log(arr.pop());  //4
    console.log(arr);  //[1, 2, 3]
    
    • shift() 删除数组的第一个元素
    //会修改原数组
    //返回值:被删除的数据
    //只能删除一个
    var arr=[1,2,3,4];
    console.log(arr.shift());  //1
    console.log(arr);  //[2, 3, 4]
    
    • splice() 万能的添加与删除 ★★★★★
    //arr.splice(位置,删除元素的个数,要追加的元素)
    //添加或者删除包括其下标
    //添加个数时,删除元素的个数为0
    //可以同时删除和添加(先删除,后添加)
    //修改原数组
    //返回值:删除的元素
    
    var arr=[1,2,3,4,7,8,'a','b','c'];
    //删除
    console.log(arr.splice(4,2));  //[7,8]
    console.log(arr);//[1, 2, 3, 4, "a", "b", "c"]
    //添加
    console.log(arr.splice(4,0,'x','y'));  //[]
    console.log(arr);//[1, 2, 3, 4, "x", "y", "a", "b", "c"]
    //先删除再添加
    console.log(arr.splice(4,2,'t','a','n')); // ["x", "y"]
    console.log(arr);//[1, 2, 3, 4, "t", "a", "n", "a", "b", "c"]
    
  • join() 将数组转换为字符串 ★★★★★

//不修改原数组
//返回值是分隔好的字符串
var arr=[1,2,3,4,7,8,'a','b','c'];
console.log(arr.join());  //1,2,3,4,7,8,a,b,c
console.log(arr.join("-"));   //1-2-3-4-7-8-a-b-c
  • slice(起始下标,结束下标) 截取数组 ★★★★★

    • 包含起始下标,不包含结束下标
    • 识别负数,-1代表最后一个位置
    • 截取到末尾,一般不写结束下标
    • 不修改原数组
    • 返回值是截取到的数组
    var arr=[1,2,3,4,7,8,'a','b','c'];
    console.log(arr.slice(4,6));//[7, 8]
    console.log(arr.slice(4));// [7, 8, "a", "b", "c"]
    console.log(arr.slice(4,-3));// [7, 8]
    
  • concat() 多个数组的拼接 ★★★

//不修改原数组
//返回值是连接之后的新数组
var arr=[1,2,3,4,'a','b','c'];
console.log(arr.concat(['t','r','h']));//[1, 2, 3, 4, "a", "b", "c", "t", "r", "h"]
  • indexOf() 返回指定值在数组中首次出现的位置 ★★★
//返回值是数据的下标,没有找到则返回-1
var arr=[1,2,3,5,4,6,1,5,6,7];
console.log(arr.indexOf(1));//0
console.log(arr.indexOf(8));//-1
  • lastIndexOf() 倒序返回指定值在数组中首次出现的位置 ★★★
var arr=[1,2,3,5,4,6,1,5,6,7];
console.log(arr.lastIndexOf(1));//6
  • sort() 数组的排序

    //如果没有参数,则从字符的编码开始按顺序排
    //如果有参数,这个参数必须是一个函数(回调函数),这个回调函数有两个参数,分别是a,b
    //会修改原数组
    //返回值是排序之后的数组
    var arr=[1,5,9,7,6,3,4,10];
    arr.sort(function(a,b){
    return a-b;//正序
    });
    console.log(arr);
    arr.sort(function(a,b){
    return b-a;//倒序
    });
    console.log(arr);
    

- forEach()   遍历数组  ★★★★★★★★★★

```js
//接收一个回调函数,回调函数第一个参数是数组值,第二个参数是下标
      var arr=[1,2,3,4,5,6];
      arr.forEach(function(value,index){
          console.log(value,index);
      });
  • filter() 过滤,从一个集合到另一个更小的集合 ★★★★★★★★★★
//根据回调函数的返回值进行元素筛选,返回值是true,元素保留;false,元素跳过
//不修改原数组
//返回值是筛选之后的数组
        var arr=[1,2,3,4,5,6];
        var newArr=arr.filter(function(value,index){
            return value>2;
        });
        console.log(newArr);  //[3, 4, 5, 6]
  • map() 映射 一一对应
//将回调函数每次的返回值,组成一个新的数组
//返回值是映射改变之后的数组
//不修改原数组
        var arr=[1,2,3,4,5,6];
		var a=arr.map(function(value,index){
            return value*2;
        });
        console.log(a);//[2, 4, 6, 8, 10, 12]
  • some() 一些满足条件就返回true
//不修改原数组     
		var arr=[1,2,3,4,5,6];
        var b=arr.some(function(value,index){
            return value>2;
        });
        console.log(b);  //true
  • every() 全部满足条件就返回true
//不修改原数组
		var arr=[1,2,3,4,5,6];
        var c=arr.every(function(value,index){
            return value>2;
        });
        console.log(c);//false
  • reverse() 数组倒序
//返回修改后的数组
//会修改原数组
console.log(arr.reverse());//[6, 5, 4, 3, 2, 1]
console.log(arr);//[6, 5, 4, 3, 2, 1]
  • includes() 用于检查数组是否包含某元素,包含返回true,否则返回false
        var arr=[1,2,{"name":"tan"}];
        console.log(arr.includes(1));  //true
        console.log(arr.includes({"name":"tan"}));  //false
//引用数据类型比较地址   基本数据类型比较值

String对象

属性
  • length
方法
  • charAt(index)

    • 返回下标为index的子字符串
    • 参数是下标
    • 返回值是对应下标的字符串
            var str="abcdefg123abcde123";
            console.log(str.charAt(3));  //d
    
  • charCodeAt(index)

    • 根据下标,返回对应下标的字符串的ASCII码
    • 参数是下标
    • 返回值是对应下标的字符串的ASCII码
            var str="abcdefg123abcde123";
            console.log(str.charCodeAt(3));//100
    
  • String.fromCharCode(97)

    • 将ASCII码转化为字符串
    • 参数是十进制的ASCII码
    • 返回值是对应的字符串
    console.log(String.fromCharCode(97));//a
    
  • indexOf()

    • 查找一个字符或者字符串在字符串中第一次出现的位置,未找到返回-1
    • 参数是要查找的字符串
    • 返回值:目标字符串的下标位置,未找到返回-1
  • lastIndexOf()

  • replace(“替换的内容”,“替换后的内容”)

    • 将指定的字符串替换,只能替换第一个
    • 返回替换后的字符串
    • 不修改原字符串
    var str="abcdefg123abcde123";
    console.log(str.replace("123","ABC"));//abcdefgABCabcde123
    
  • slice(起始下标,结束下标)

    • 与数组相同
  • substring(起始下标,结束下标)

    • 与slice用法相同,但是不识别负数
  • substr(起始下标,截取的长度)

  • split()

    • 以某一字符串将目标字符串分割
    • 参数是以什么字符串分割
    • 返回分割之后的字符串组成的数组
    • 注意,返回值中传入的字符串会被删掉,不修改原字符串
    var str="abcdefg123abcde123abcd";
    console.log(str.split("123"));//["abcdefg", "abcde", "abcd"]
    console.log(str.split());//["abcdefg123abcde123abcd"]
    console.log(str.split(""));//["a", "b", "c", "d", "e", "f", "g", "1", "2", "3", "a", "b", "c", "d", "e", "1", "2", "3", "a", "b", "c", "d"]
    
  • toLowerCase()

    • 将字符串中的字符转化为小写,不修改原字符串
  • toUpperCase()

    • 将字符串中的字符转化为大写,不修改原字符串
  • trim()

    • 将字符串左右的空格去掉,但是去不掉中间的
  • match()

  • concat()字符串拼接

Object对象

  • Object.assign(obj1,obj2,…)

    • 用于对象的拼接,将obj2,obj3…拼接到对象obj1,并将obj1返回,obj改变,其他对象不变。
  • Object.is(a,b)

    • 用于判断两个值是否相同,与===类似
    Object.is(NaN,NaN);  //true
    
  • obj.prototype.isPrototypeOf(b)

    • 确定一个对象是否存在于另一个对象的原型链中
  • Object.keys(obj)

    • 返回一个数组,包括对象自身的所有可枚举的属性的键名
  • Object.values(obj)

    • 键值

**原型/原型对象(prototype)

  • 构造函数的属性

  • 作用:

    • 存放公共的属性与方法来节省内存
    • 实现继承
  • 语法:json格式

    function Person(sex){
        this.sex=sex;
    }
    Preson.prototype={
        height:"180",
        eat:function(){}
    }
    

**原型链

在访问对象的属性与方法时遵循的一条链式规则。

  • 访问顺序:对象自身→构造函数→构造函数的原型对象→原型链
  • 如何串联:__proto__
    • 对象的属性
    • 指向构造函数的原型对象

BOM 浏览器对象模型

管理窗口与窗口之间的通信,核心对象是window对象。

window对象

自定义的变量或者是函数,可以看作window对象的属性与方法。函数内部的this会指向window。

属性

  • window.innerHeight 获取浏览器窗口的高度
  • window.innnerWidth 获取浏览器窗口的宽度

方法

  • alert()
  • prompt()
  • confirm()
  • open() 打开新窗口
  • close() 关闭本窗口

时间函数(定时器)

  • setInterval(callback,times) 指定时间间隔执行回调函数
  • clearInterval(t) 清除时间函数
  • setTimeOut(callback,times) 间隔一定时间只执行一次回调函数
  • clearTimeOut(t) 清除时间函数

DOM 文档对象模型

Document Object Model 。文档与文档之间

获取元素

  • 获取匹配到的第一个元素
document.querySelector("选择器")   //获取到的是一个元素
  • 获取匹配到的全部元素
document.querySelectorAll("选择器")  //获取到的不是数组,是节点列表
  • 通过标签名获取元素
document.getElementsByTagName("标签名")  //获取到的是集合
  • 通过类名获取元素
document.getElementsByClassName("类名")  //获取到的是集合
  • 通过id名获取元素
document.getElementById("id名")   //获取到的是一个元素

操作html属性

  • 原生属性(标准属性)
对象.属性名=属性值
对象.className="类名";

input.type="password";
  • 非标准属性(自定义属性)
    • 设置:obj.setAttribute(属性名,属性值)
    • 获取属性内容:obj.getAttribute(属性名)
    • 检测:obj.hasAttribute(属性名) 返回truefalse
    • 移除:obj.removeAttribute(属性名)

操作样式(css属性)

  • 行内样式
元素.style.样式=;
box.style.backgroundColor="red";
  • 批量添加样式

    • 添加类名
    obj.classList.add("类名");
    
    • 移除类名
    obj.classList.remove("类名");
    
    • 添加id
    obj.id="id名";
    
    • 移除id
    obj.id="";
    
  • 获取样式

    • getComputedStyle(操作的元素,null).css属性
    getComputedStyle(obj,null).width   
    

操作内容

  • 元素.innerText
  • 元素.innerHTML 可以识别标签对
  • 表单元素.value

事件

事件的三要素:

事件源.事件类型=事件处理函数

box.onclick=function(){
    this.style.marginTop="20px";
}
  • onclick 点击
  • onmouseenter 鼠标移入
  • onmouseleave 鼠标移走

事件添加方式

  • 行内样式
<div onclick="fn()"></div>
  • on + type
btn.onclick=function(){
    
}

//移除
btn.onclick=null
  • 事件监听:允许同一个对象的同一个事件类型绑定多个事件处理函数
btn.addEventListener(事件类型,回调函数,boolean)
//有三种回调函数的格式
btn.addEventListener("click",function(){
	this.style.backgroundColor="pink";
},false);
btn.addEventListener("click",function(){
	this.style.borderRadius="50%";
},false)
btn.addEventListener("click",fn,false);


//移除  只能写函数名
btn.removeEventListener(事件类型,函数名,boolean)

事件对象

记录事件发生时的详细信息。事件处理程序的第一个参数代表事件对象

btn.onclick=function(event){
    var e=event||window.event;  //事件的兼容性写法
}
//解构赋值
var {key,keyCode}=event;
鼠标事件对象的属性
  • clientX 获取鼠标点击的位置距离浏览器左上角水平方向的距离
  • clientY 获取鼠标点击的位置距离浏览器左上角垂直方向的距离
  • offsetX 获取鼠标点击的位置距离事件源左上角水平方向的距离
  • offsetY 获取鼠标点击的位置距离事件源左上角垂直方向的距离
方法
  • e.preventDefault() 屏蔽浏览器的默认行为 javascript:;
  • e.stopPropagation() 阻止冒泡事件流

事件流

事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流。

两种事件流模型
  • 冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标
//两种写法
//1.on+type
son.onclick=function(){
	console.log("son");
}
father.onclick=function(){
	console.log("father");
}
document.body.onclick=function(){
	console.log("body");
} 

//2.addEventListener  的false
son.addEventListener("click",function(){
	console.log("son");
},false);
father.addEventListener("click",function(){
	console.log("father");
},false);
document.body.addEventListener("click",function(){
	console.log("body");
},false);

//如何阻止冒泡事件   用stopPropagation()
son.addEventListener("click",function(e){
	var event=e||window.event;
	event.stopPropagation(); //阻止冒泡
	console.log("son");
},false);
  • 捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标
son.addEventListener("click",function(){
	console.log("son");
},true);
father.addEventListener("click",function(){
	console.log("father");
},true);
document.body.addEventListener("click",function(){
	console.log("body");
},true);
DOM事件流的三个阶段

DOM标准规定事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
eventPhase属性返回一个整数值,表示事件目前所处的事件流阶段:0表示事件没有发生,1表示捕获阶段,2表示目标阶段,3表示冒泡阶段 。

  1. 事件捕获阶段:实际目标div在捕获阶段不会接收事件。也就是在捕获阶段,事件从documenthtml再到body就停止了。
  2. 处于目标阶段:事件在div上发生并处理。但是事件处理会被看成是冒泡阶段的一部分。
  3. 冒泡阶段:事件又传播回文档。
  4. 所有的事件都要经过捕获阶段和处于目标阶段,但是有些事件会跳过冒泡阶段:如,获得输入焦点的focus事件和失去输入焦点的blur事件。

事件委派

概念

把子元素的事件添加到父元素身上,并且父元素能够通过target判断是哪个元素,从而做出相应的处理。

原理

冒泡型事件流

适用场景
  1. 给大量的元素添加事件处理程序时,提高运行效率
  2. 给页面加载完成后新创建的元素添加事件
用法
  • 子元素的事件加到父元素身上

  • 触发事件时判断,触发该事件的元素是什么

    • 用nodeName判断标签
    if(elem.nodeName=="H1"){
    	father.style.backgroundColor="pink";
    }
    
    • 用innerHTML或者innerText判断内容
    if(elem.innerHTML=="这是h1"){
    	father.style.backgroundColor="red";
    }
    
    • 通过属性名判断 元素.hasAttribute(“属性名”)
    if(elem.hasAttribute("id")){
    	father.style.backgroundColor="red";
    }
    
    • 通过判断是否有类名 元素.classList.contains(“类名”)
    if(elem.classList.contains("son")){
    	father.style.backgroundColor="red";
    }
    
  • 在判断成功中写对应的处理函数

节点

在html DOM中,所有事物都是节点,DOM被视为节点树的html。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

节点的种类

节点分类节点类型(node Type)节点名称(node Name)节点内容(node Value)包含
元素节点1标签名null每个html元素都是元素节点
属性节点2属性名属性值每个html属性都是属性节点
文本节点3#text文本文字、空格、换行
注释节点8#comment注释文本文档中的注释
文档节点9#documentnull整个文档是一个文档节点
节点属性
属性描述
node.parentNode获取父节点
node.childNodes获取子节点
node.firstChild第一个子节点
node.lastChild最后一个子节点
node.nextSibling下一个兄弟节点
node.previousSibling上一个兄弟节点
属性可读描述
element.parentElement只读获取父元素
ParentNode.children只读获取所有子元素
ParentNode.childElementCount只读获取子元素的数量
ParentNode.firstElementChild只读第一个子元素
ParentNode.lastElementChild只读最后一个子元素
ParentNode.nextElementSibling只读下一个元素
ParentNode.previousElementSibling只读上一个元素
节点的方法
方法描述
document.createElement()创建一个元素节点
document.createTextNode()创建一个文本节点
parent.appendChild(子节点)插入一个子节点
parent.insertBefore(要插入的节点,插入到某个元素之前)插入到某个节点之前
parent.removeChild(子节点)删除子节点
parent.replaceChild(新节点,要被修改的节点)替换节点
node.cloneNode()克隆节点
//首先获取到父元素
var box=document.querySelector(".box");
//创建新标签(元素)
var spans=document.createElement("spans");
//添加内容
spans.innerHTML="这是span标签";
 //插入父元素
box.appendChild(spans);

元素的尺寸与位置

  • offsetWidth 获取元素的真实宽度(内容+内填充+边框)
  • offsetHeight 获取元素的真实高度
  • offsetLeft 获取元素的左上角(边框以外)距有定位属性的父元素左上角(边框以内)水平方向的距离
  • offsetTop 获取元素左上角(边框以外)距有定位属性的父元素左上角(边框以内)垂直方向的距离
  • offserParent 获取距离该元素最近的具有定位属性的父元素
  • scrollTop 获取具有滚动条的元素在滚动时,滚动条距里顶部的距离(垂直方向滚动的距离)
  • scrollLeft 获取具有滚动条的元素在滚动时,滚动条水平方向滚动的距离
//监测页面的滚动事件
window.onscroll=function(){
    //获得滚动的距离   兼容性的写法
    document.body.scrollTop||document.documentElement.scrollTop
}

表单操作

表单form

获取form对象
  • document.getElementById()
  • document.getElementByName()
  • document.getElementByTagName()
  • document.name 只适用于表单
form对象属性
属性描述
action接收请求的URL
elements表单中的所有控件元素集合
length表单控件的个数
enctype编码类型
name表单元素名称
form对象方法
方法描述
reset()把表单的所有输入元素重置为它们的默认值
submit()提交表单
form对象事件
事件描述
onreset在重置表单元素之前调用
onsubmit在提交表单之前调用
表单元素
获取表单元素
//除以上方法还可利用属性获取表单元素
var btn=document.querySelector("[type=button]");
表单控件的属性
属性描述
value获取和设置值
disabled获取或设置表单控件是否禁用,值为true或false
type读取表单控件的类型
form所在表单元素对象
readOnly控件只读属性 Boolean 不能更改只能复制和读取
name获取与设置name字段名
表单控件的事件
事件描述
onblur当失去焦点的时候
onfocus当获取焦点的时候
onchange当内容改变并失去焦点的时候
oninput在用户输入时触发,并实时监控
表单控件的方法
方法描述
focus()获得焦点
blur()失去焦点
select()选择文本控件中的所有文本内容
select控件属性
属性描述
length选项的个数
size取得size属性
multiple是否是多选 Boolean类型
options所有option选项
selectedIndex设置或返回的选中索引值
selected设置或返回选项的选中状态
option控件属性
属性描述
index选项在options的索引值
selected当前selected是否选中 Boolean
text文本内容
valuevalue属性的值
单选、多选控件
属性描述
checked返回或者设置单选的选中状态,true选中 false未选中
value属性 获取选中的值,必须先判断选中状态

本地存储

将数据存储到客户端或者浏览器端。有三种,cookie,localStorage,sessionStorage。

cookie

Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息。无论何时用户链接到服务器,Web 站点都可以访问 Cookie 信息。每个cookie不能超过 4KB,每个 Web 站点能设置的 Cookie 总数不能超过 20 个 。

特点
类别描述
存储方式键值对
大小4kb,以20个为上限
访问根据域名存储,不同域名的cookie无法访问
清理机制IE和Opera 会清理近期最少使用的cookie,Firefox会随机清理cookie。
缺陷同域内http请求都会带cookie,浪费带宽
应用购物车,登录状态
localStorage

H5客户端存储是web存储的一种更为强大的版本,可提供更多的安全性、速度和易用性。在 Web 中可以存储数量巨大的数据。具体的数量则取决于 Web 浏览器,但通常都在 5MB 到10MB 之间,这对于一个 HTML应用程序而言已经足够大。另一个好处是此数据并不会在每次出现服务器请求时都被加载。

操作
方法描述
localStorage.length获得storage中的个数
localStorage .key(n)获得storage中第n个键值对的键
localStorage.key = value添加
localStorage.setItem(key, value)添加
localStorage.getItem(key)获取
localStorage.removeItem(key)移除
localStorage.clear()清除
        localStorage.setItem("name","檀糖");
        localStorage.setItem("age",22);
        localStorage.sex="女";
        console.log(localStorage.getItem("name"));
        console.log(localStorage.key(0));
        console.log(localStorage.length);
        localStorage.removeItem("sex");
        localStorage.clear();
sessionStroage

短期存储,页面关闭后存储消失,其他与长期存储一样。

方法描述
获得storage中的个数
获得storage中第n个键值对的键
不同点:
  • 大小

    • cookie 4kb
    • localStorage 5mb-10mb
    • sessionStorage
  • 存储时间

    • cookie

    • localStorage:永久性

    • sessionStorage:一次会话

JSON

轻量级的数据交换格式

  • JSON.stringify()将对象转换成字符串
  • JSON.parse()将字符串转换成对象,必须是对象格式的字符串

JS异步

  • 事件
  • 时间函数
  • ajax

功能

发送请求和接受数据。

插件

swiper 轮播图效果

swiper-animate H5页面

lazyload 懒加载

参阅:
[1]: https://blog.csdn.net/weiyong1999/article/details/7916691
[2]: https://zhuanlan.zhihu.com/p/62762377
[3]: https://blog.csdn.net/weixin_45301250/article/details/119336522

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值