1 JS简介

更多JS内容可以看MDN:点击传送 浏览器分成两部分:渲染引擎和 JS 引擎

  • 渲染引擎:用来解析HTML与CSS,俗称内核,比如 chrome 浏览器的 blink ,老版本的 webkit
  • JS 引擎:也称为 JS 解释器。 用来读取网页中的JavaScript代码,对其处理后运行,比如 chrome 浏览器的 V8

浏览器本身并不会执行JS代码,而是通过内置 JavaScript 引擎(解释器) 来执行 JS 代码 。JS 引擎执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以 JavaScript 语言归为脚本语言,会逐行解释执行。

go 的javascript解释器引擎 js解释器有哪些_前端

1.1 ECMAScript

ECMAScript 是由ECMA 国际( 原欧洲计算机制造商协会)进行标准化的一门编程语言,这种语言在万维网上应用广泛,它往往被称为 JavaScript 或 JScript,但实际上后两者是 ECMAScript 语言的实现和扩展。

go 的javascript解释器引擎 js解释器有哪些_面试_02


ECMAScript:ECMAScript 规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。

1.2 DOM-文档对象模型

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言的标准编程接口。通过 DOM 提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)。

1.3 BOM-浏览器对象模型

BOM (Browser Object Model,简称BOM) 是指浏览器对象模型,它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。

2 变量

变量在内存中的存储
本质:变量是程序在内存中申请的一块用来存放数据的空间。

声明变量并赋值我们称之为变量的初始化

2.1 命名规范

  • 由字母(A-Za-z)、数字(0-9)、下划线(_)、美元符号( $ )组成,如:usrAge, num01, _name
  • 严格区分大小写。var app; 和 var App; 是两个变量
  • 不能 以数字开头。 18age 是错误的
  • 不能 是关键字、保留字。例如:var、for、while
  • 变量名必须有意义。 MMD BBD nl → age
  • 遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。 myFirstName

3 数据类型

3.1简单数据类型

简单数据类型存放到栈里面

go 的javascript解释器引擎 js解释器有哪些_面试_03

3.1.1 数字型 Number

3.1.1.1 数字型范围
alert(Number.MAX_VALUE); // 1.7976931348623157e+308
alert(Number.MIN_VALUE); // 5e-324

最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
最小值:Number.MIN_VALUE,这个值为:5e-32

3.1.1.2 数字型三个特殊值
alert(Infinity);  // Infinity
alert(-Infinity); // -Infinity
alert(NaN);       // NaN

Infinity:代表无穷大,大于任何数值
-Infinity:代表无穷小,小于任何数值
NaN :Not a number,代表一个非数值

3.1.1.3 isNaN()

用来判断一个变量是否为非数字的类型,返回 true 或者 false

go 的javascript解释器引擎 js解释器有哪些_go 的javascript解释器引擎_04

3.1.2 字符串型 String

HTML 标签里面的属性使用的是双引号,JS 更推荐使用单引号。

根据位置返回字符:

go 的javascript解释器引擎 js解释器有哪些_go 的javascript解释器引擎_05

根据字符返回位置:

go 的javascript解释器引擎 js解释器有哪些_javascript_06

字符串操作方法:

go 的javascript解释器引擎 js解释器有哪些_前端_07

其他方法:

  • toUpperCase() //转换大写
  • toLowerCase() //转换小写
  • replace() //用于在字符串中用一些字符替换另一些字符
  • split() //用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。

go 的javascript解释器引擎 js解释器有哪些_数组_08

3.1.3 布尔型 Boolean

布尔型和数字型相加的时候, true 的值为 1 ,false 的值为 0

3.1.4 Undefined 和 Null

//undefined
var variable;
console.log(variable);           // undefined
console.log('你好' + variable);  // 你好undefined
console.log(11 + variable);     // NaN
console.log(true + variable);   //  NaN
//null
var vari = null;
console.log('你好' + vari);  // 你好null
console.log(11 + vari);     // 11
console.log(true + vari);   //  1

3.1.5 获取检测变量的数据类型

typeof 可用来获取检测变量的数据类型

go 的javascript解释器引擎 js解释器有哪些_前端_09

3.1.6 数据类型转换

3.1.6.1 转换为字符串

go 的javascript解释器引擎 js解释器有哪些_面试_10

3.1.6.2 转换为数字型

go 的javascript解释器引擎 js解释器有哪些_数组_11


隐式转换是我们在进行算数运算的时候,JS 自动转换了数据类型

3.1.6.3 转换为布尔型

go 的javascript解释器引擎 js解释器有哪些_前端_12


代表空、否定的值会被转换为 false ,如 ‘’、0、NaN、null、undefined

其余值都会被转换为 true

3.2 复杂类型(引用类型)

复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型
通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
复杂数据类型存放到堆里面

4 关键字和保留字

4.1 关键字

关键字:是指 JS本身已经使用了的字,不能再用它们充当变量名、方法名。
包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。

4.2 保留字

保留字:实际上就是预留的“关键字”,意思是现在虽然还不是关键字,但是未来可能会成为关键字,同样不能使用它们当变量名或方法名。
包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、fimal、float、goto、implements、import、int、interface、long、mative、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile 等。
注意:如果将保留字用作变量名或函数名,那么除非将来的浏览器实现了该保留字,否则很可能收不到任何错误消息。当浏览器将其实现后,该单词将被看做关键字,如此将出现关键字错误。

5 运算符

JavaScript中常用的运算符有:

  • 算数运算符
  • 递增和递减运算符
  • 比较运算符
  • 逻辑运算符
  • 赋值运算符

5.1 算数运算符

+ - * / %

浮点数的精度问题

var result = 0.1 + 0.2;    // 结果不是 0.3,而是:0.30000000000000004
console.log(0.07 * 100);   // 结果不是 7,  而是:7.000000000000001

注:不要直接判断两个浮点数是否相等

5.2 递增和递减运算符

如果需要反复给数字变量添加或减去1,可以使用递增(++)和递减( – )运算符来完成。
++num 前置递增:先自加,后返回值
num++:先返回原值,后自加

5.3 比较运算符

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

go 的javascript解释器引擎 js解释器有哪些_面试_13

5.4 逻辑运算符

逻辑与&& 逻辑或|| 取反符!

5.5 赋值运算符

= += -= *= /= %=

5.6 运算符优先级

go 的javascript解释器引擎 js解释器有哪些_面试_14

  • 一元运算符里面的逻辑非优先级很高
  • 逻辑与比逻辑或优先级高

6 流程控制

流程控制主要有三种结构,分别是顺序结构、分支结构和循环结构,这三种结构代表三种代码执行的顺序。

6.1 顺序流程控制

程序会按照代码的先后顺序,依次执行

6.2 分支流程控制

JS 语言提供了两种分支结构语句

  • if 语句
  • switch 语句

6.2.1 if

if (条件表达式1) {
    语句1;
} else if (条件表达式2)  {
    语句2;
} else if (条件表达式3)  {
   语句3;
 ....
} else {
    // 上述条件都不成立执行此处代码
}

6.2.2 switch

switch( 表达式 ){ 
    case value1:
        // 表达式 等于 value1 时要执行的代码
        break;
    case value2:
        // 表达式 等于 value2 时要执行的代码
        break;
    default:
        // 表达式 不等于任何一个 value 时要执行的代码
}

关键字 switch 后面括号内可以是表达式或值, 通常是一个变量
注: 执行case 里面的语句时,如果没有break,则继续执行下一个case里面的语句。

6.2.3 三元表达式

表达式1 ? 表达式2 : 表达式3;

如果表达式1为 true ,则返回表达式2的值,如果表达式1为 false,则返回表达式3的值

6.3 循环

在Js 中,主要有三种类型的循环语句:

  • for 循环
  • while 循环
  • do…while 循环

6.3.1 for 循环

for(初始化变量; 条件表达式; 操作表达式){
    //循环体语句
}

6.3.2 while循环

while (条件表达式) {
    // 循环体代码 
}

使用 while 循环时一定要注意,它必须要有退出条件,否则会成为死循环

6.3.3 do while 循环

do {
    // 循环体代码 - 条件表达式为 true 时重复执行循环体代码
} while(条件表达式);

先再执行循环体,再判断,我们会发现 do…while 循环语句至少会执行一次循环体代码

6.3.4 continue break

continue: 用于立即跳出本次循环,继续下一次循环。
break: 用于立即跳出整个循环(循环结束)。

7 数组

JS 中创建数组有两种方式:

  • 利用 new 创建数组
  • 利用数组字面量创建数组
var 数组名 = new Array();
var  数组名 = [];

7.1 检测是否为数组

instanceof 运算符,可以判断一个对象是否属于某种类型
Array.isArray()用于判断一个对象是否为数组,isArray() 是 HTML5 中提供的方法

var arr = [1, 23];
var obj = {};
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
console.log(Array.isArray(arr));   // true
console.log(Array.isArray(obj));   // false

7.2 添加删除数组元素的方法

go 的javascript解释器引擎 js解释器有哪些_面试_15

7.3 数组排序

go 的javascript解释器引擎 js解释器有哪些_go 的javascript解释器引擎_16

7.4 数组索引方法

go 的javascript解释器引擎 js解释器有哪些_go 的javascript解释器引擎_17

7.5 数组转换为字符串

go 的javascript解释器引擎 js解释器有哪些_javascript_18

7.6 其他方法

go 的javascript解释器引擎 js解释器有哪些_数组_19

8 函数

概念:封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。

// 声明函数
function 函数名() {
    //函数体代码
}

// 调用函数
函数名();

注:声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码。

break :结束当前的循环体(如 for、while)
continue :跳出本次循环,继续执行下次循环(如 for、while)
return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码

8.1 arguments的使用

当我们不确定有多少个参数传递的时候,可以用 arguments 来获取。在 JavaScript 中,arguments 实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。

arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:

  • 具有 length 属性
  • 按索引方式储存数据
  • 不具有数组的 push , pop 等方法

9 对象

在 JavaScript 中,现阶段我们可以采用三种方式创建对象(object):

  • 利用字面量创建对象
  • 利用 new Object 创建对象
  • 利用构造函数创建对象

9.1 利用字面量创建对象

//创建
var star = {
    name : 'zhangsan',
    age : 18,
    sex : '男',
    sayHi : function(){
        alert('大家好啊~');
    }
};

//调用
console.log(star.name)     // 调用名字属性
console.log(star['name'])  // 调用名字属性
star.sayHi();              // 调用 sayHi 方法,注意,一定不要忘记带后面的括号

9.2 利用new Object创建对象

var andy = new Obect();
andy.name = 'zhangsan';
andy.age = 18;
andy.sex = '男';
andy.sayHi = function(){
    alert('大家好啊~');
}

9.3 利用构造函数创建对象

构造函数 :是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。

在 js 中,使用构造函数要时要注意以下两点:

  • 构造函数用于创建某一类对象,其首字母要大写
  • 构造函数要和 new 一起使用才有意义
function Person(name, age, sex) {
     this.name = name;
     this.age = age;
     this.sex = sex;
     this.sayHi = function() {
      alert('我的名字叫:' + this.name + ',年龄:' + this.age + ',性别:' + this.sex);
    }
}
var bigbai = new Person('大白', 100, '男');
var smallbai = new Person('小白', 21, '男');
console.log(bigbai.name);
console.log(smallbai.name);

注意:

  1. 构造函数约定首字母大写。
  2. 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
  3. 构造函数中不需要 return 返回结果。
  4. 当我们创建对象的时候,必须用 new 来调用构造函数。

9.4 遍历对象属性

for…in 语句用于对数组或者对象的属性进行循环操作。

for (var k in obj) {
    console.log(k);      // 这里的 k 是属性名
    console.log(obj[k]); // 这里的 obj[k] 是属性值
}

10 内置对象

内置对象就是指 JS 语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法)
JavaScript 提供了多个内置对象:Math、 Date 、Array、String等

10.1 Math对象

Math 对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用 Math 中的成员。

Math.PI		  // 圆周率
Math.floor()  // 向下取整
Math.ceil()   // 向上取整
Math.round()  // 四舍五入版 就近取整   注意 -3.5   结果是  -3 
Math.abs()	  // 绝对值
Math.max()/Math.min()	 // 求最大和最小值

10.1.1 随机数方法 random()

random() 方法可以随机返回一个小数,其取值范围是 [0,1),左闭右开 0 <= x < 1

得到一个两数之间的随机整数,包括两个数在内

function getRandom(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min; 
}

10.2 日期对象

var now = new Date();

如果括号里面有时间,就返回参数里面的时间。例如日期格式字符串为‘2019-5-1’,可以写成new Date(‘2019-5-1’) 或者 new Date(‘2019/5/1’)

日期格式化:

go 的javascript解释器引擎 js解释器有哪些_面试_20

获取日期的总的毫秒形式:

// 实例化Date对象
var now = new Date();
// 1. 用于获取对象的原始值
console.log(date.valueOf())	
console.log(date.getTime())	
// 2. 简单写可以这么做
var now = + new Date();			
// 3. HTML5中提供的方法,有兼容性问题
var now = Date.now();

11 操作DOM

11.1 DOM简介

go 的javascript解释器引擎 js解释器有哪些_javascript_21

  • 文档:一个页面就是一个文档,DOM 中使用 document 表示
  • 元素:页面中的所有标签都是元素,DOM 中使用 element 表示
  • 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示

DOM 把以上内容都看做是对象

11.2 获取页面元素

获取页面中的元素可以使用以下几种方式:

  • 根据 ID 获取
  • 根据标签名获取
  • 通过 HTML5 新增的方法获取
  • 特殊元素获取

11.2.1 根据id获取

使用 getElementById() 方法可以获取带有 ID 的元素对象。

document.getElementById('id');

使用 console.dir() 可以打印我们获取的元素对象,更好的查看对象里面的属性和方法。

11.2.2 根据标签名获取

使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。

document.getElementsByTagName('标签名');

注意:

  1. 因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历。
  2. 得到元素对象是动态的
  3. 如果获取不到元素,则返回为空的伪数组(因为获取不到对象)

还可以获取某个元素(父元素)内部所有指定标签名的子元素.

element.getElementsByTagName('标签名');

注意:父元素必须是单个对象(必须指明是哪一个元素对象). 获取的时候不包括父元素自己。

11.2.3 通过 HTML5 新增的方法获取

1. document.getElementsByClassName(‘类名’);// 根据类名返回元素对象集合
2. document.querySelector('选择器');        // 根据指定选择器返回第一个元素对象
3. document.querySelectorAll('选择器');     // 根据指定选择器返回

注意:
querySelector 和 querySelectorAll里面的选择器需要加符号,比如:document.querySelector(‘#nav’);

11.2.4 classList 属性

classList属性是HTML5新增的一个属性,返回元素的类名。但是ie10以上版本支持。
该属性用于在元素中添加,移除及切换 CSS 类。

11.2.4.1 添加类

element.classList.add(’类名’):

11.2.4.2 移除类

element.classList.add(’类名’):

11.2.4.3 切换类

element.classList.toggle(’类名’):

注意:以上方法里面,所有类名都不带点

11.2.5 获取特殊元素(body,html)

doucumnet.body  // 返回body元素对象
document.documentElement  // 返回html元素对象

11.3 事件

11.3.1 常见的鼠标事件

go 的javascript解释器引擎 js解释器有哪些_前端_22

  1. 禁止鼠标右键菜单
    contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
document.addEventListener('contextmenu', function(e) {
   e.preventDefault();
})
  1. 禁止鼠标选中(selectstart 开始选中)
document.addEventListener('selectstart', function(e) {
	e.preventDefault();
})
  1. mouseenter 和mouseover的区别
  • 当鼠标移动到元素上时就会触发 mouseenter 事件
  • 类似 mouseover,它们两者之间的差别是
  • mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。 mouseenter 只会经过自身盒子触发
  • 之所以这样,就是因为mouseenter不会冒泡
  • 跟mouseenter搭配 鼠标离开 mouseleave 同样不会冒泡

11.3.2 常用的键盘事件

go 的javascript解释器引擎 js解释器有哪些_前端_23


注意: onkeydown 和 onkeyup 不区分字母大小写,onkeypress 区分字母大小写。

在实际开发中,更多的使用keydown和keyup, 它能识别所有的键(包括功能键)

Keypress 不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值

go 的javascript解释器引擎 js解释器有哪些_前端_24

11.3.3 注册事件(绑定事件)

给元素添加事件,称为注册事件或者绑定事件。

注册事件有两种方式:传统方式和方法监听注册方式

go 的javascript解释器引擎 js解释器有哪些_go 的javascript解释器引擎_25

11.3.3.1 addEventListener 事件监听方式
eventTarget.addEventListener(type, listener[, useCapture])

将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。

  • type:事件类型字符串,比如 click 、mouseover ,注意这里不要带 on
  • listener:事件处理函数,事件发生时,会调用该监听函数
  • useCapture:可选参数,是一个布尔值,默认是 false。
11.3.3.2 attachEvent 事件监听方式
eventTarget.attachEvent(eventNameWithOn, callback)

将指定的监听器注册到 eventTarget(目标对象) 上,当该对象触发指定的事件时,指定的回调函数就会被执行。

  • eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
  • callback: 事件处理函数,当目标触发事件时回调函数被调用

注意:IE8 及早期版本支持

11.3.4 删除事件(解绑事件)

1. 传统注册方式
eventTarget.onclick = null;

2. 方法监听注册方式
① eventTarget.removeEventListener(type, listener[, useCapture]);
② eventTarget.detachEvent(eventNameWithOn, callback);

11.3.5 DOM 事件流

事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流。
比如我们给一个div 注册了点击事件:
DOM 事件流分为3个阶段:

  1. 捕获阶段
  2. 当前目标阶段
  3. 冒泡阶段

    事件冒泡: IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程。
    事件捕获: 网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。

    事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流。

注意:

  • JS 代码中只能执行捕获或者冒泡其中的一个阶段。
  • onclick 和 attachEvent 只能得到冒泡阶段。
  • addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
  • 实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
  • 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
  • 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件。

11.3.6

eventTarget.onclick = function(event) {} 
eventTarget.addEventListener('click', function(event) {})
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt

官方解释:event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。

11.3.6.1 事件对象本身的获取存在兼容问题:
  1. 标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。
  2. 在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找。

解决:
e = e || window.event;

11.3.6.2 事件对象的常见属性和方法

e.target 和 this 的区别:

  • this 是事件绑定的元素, 这个函数的调用者(绑定这个事件的元素)
  • e.target 是事件触发的元素。

go 的javascript解释器引擎 js解释器有哪些_面试_26

11.3.7 阻止事件冒泡

事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点。
事件冒泡本身的特性,会带来的坏处,也会带来的好处

  • 标准写法:利用事件对象里面的 stopPropagation()方法
    e.stopPropagation()
  • 非标准写法:IE 6-8 利用事件对象 cancelBubble 属性
    e.cancelBubble = true;

11.3.8 事件委托(代理、委派)

事件冒泡本身的特性,会带来的坏处,也会带来的好处

例子:
<ul>
	<li>点击出现对话框</li>
	<li>点击出现对话框</li>
	<li>点击出现对话框</li>
	<li>点击出现对话框</li>
	<li>点击出现对话框</li>
</ul>

//点击每个 li 都会弹出对话框,以前需要给每个 li 注册事件,是非常辛苦的,而且访问 DOM 的次数越多,这就会延长整个页面的交互就绪时间。

事件委托
事件委托也称为事件代理, 在 jQuery 里面称为事件委派。
事件委托的原理
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
以上案例:给 ul 注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击 li,事件会冒泡到 ul 上, ul 有注册事件,就会触发事件监听器。
事件委托的作用
我们只操作了一次 DOM ,提高了程序的性能。

11.4 操作元素

JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内容 、属性等。注意以下都是属性

11.4.1 改变元素内容

// 从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去掉
element.innerText

//起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行
element.innerHTML

src、href、id、alt、title等

11.4.2 表单元素的属性操作

利用 DOM 可以操作如下表单元素的属性:
type、value、checked、selected、disabled

11.4.3 样式属性操作

我们可以通过 JS 修改元素的大小、颜色、位置等样式。

1. element.style     行内样式操作
2. element.className 类名样式操作

注意:

  1. JS 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor
  2. JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
  3. className 会直接更改元素的类名,会覆盖原先的类名。

11.4.4 小结

go 的javascript解释器引擎 js解释器有哪些_javascript_27

11.4.5 自定义属性的操作

获取属性值:
element.属性 获取属性值。(元素本身自带的属性)
element.getAttribute(‘属性’); 主要获得自定义的属性 (标准)自定义的属性

设置属性值:
element.属性 = ‘值’ 设置内置属性值。
element.setAttribute(‘属性’, ‘值’); 主要设置自定义的属性 (标准)

移除属性
element.removeAttribute(‘属性’);

11.4.6 H5自定义属性

自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
自定义属性获取是通过getAttribute(‘属性’) 获取。
但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。

11.4.6.1 设置H5自定义属性

H5规定自定义属性data-开头做为属性名并且赋值。
比如 <div data-index=“1”></div> 或者使用 JS 设置
element.setAttribute(‘data-index’, 2)

11.4.6.2 获取H5自定义属性

兼容性获取 element.getAttribute(‘data-index’);
H5新增 element.dataset.index 或者 element.dataset[‘index’] ie 11才开始支持

11.5 操作节点

11.5.1 父级节点

node.parentNode parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
如果指定的节点没有父节点则返回 null

11.5.2 子节点

parentNode.childNodes(标准)
`返回包含指定节点的子节点的集合,该集合为即时更新的集合。
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。
如果只想要获得里面的元素节点,则需要专门处理。 所以一般不提倡使用childNodes`

parentNode.children(非标准)
`是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回。
虽然children 是一个非标准,但是得到了各个浏览器的支持,因此可以放心使用`
parentNode.firstChild
`返回第一个子节点,找不到则返回null。包含所有的节点(包含后代)。`

parentNode.lastChild
`返回最后一个子节点,找不到则返回null。包含所有的节点(包含后代)。`
parentNode.firstElementChild
`返回第一个子元素节点,找不到则返回null。`

parentNode.lastElementChild
`返回最后一个子元素节点,找不到则返回null。` 

注意:这两个方法有兼容性问题,IE9 以上才支持。

实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和 lastElementChild 又有兼容性问题,那如何获取第一个子元素节点或最后一个子元素节点呢?
解决方案:
如果想要第一个子元素节点,可以使用 parentNode.chilren[0] 如果想要最后一个子元素节点,可以使用 parentNode.chilren[parentNode.chilren.length - 1]

11.5.3 兄弟节点

node.nextSibling
`返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。`

node.previousSibling
`返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。`
node.nextElementSibling
`返回当前元素下一个兄弟元素节点,找不到则返回null。`

node.previousElementSibling
`返回当前元素上一个兄弟节点,找不到则返回null。 `

注意:这两个方法有兼容性问题, IE9 以上才支持。

11.5.4 创建节点

document.createElement('tagName')
`创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。`

node.appendChild(child)
`将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的 after 伪元素。`

node.insertBefore(child, 指定元素)
`将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素。`

11.5.5 删除节点

node.removeChild(child) 从 DOM 中删除一个子节点,返回删除的节点。

11.5.6 复制节点(克隆节点)

node.cloneNode() 返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点
如果括号参数为空或者为 false ,只克隆复制节点本身,不克隆里面的子节点。
如果括号参数为 true ,会复制节点本身以及里面所有的子节点。

11.5.7 三种动态创建元素区别

document.write()
element.innerHTML
document.createElement()

  1. document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
  2. innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
  3. innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
  4. createElement() 创建多个元素效率稍低一点点,但是结构更清晰

总结:不同浏览器下,innerHTML 效率要比 creatElement 高

12 操作BOM

12.1 BOM概述

BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。

BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。

BOM 缺乏标准,JavaScript 语法的标准化组织是 ECMA,DOM 的标准化组织是 W3C,BOM 最初是Netscape 浏览器标准的一部分。

go 的javascript解释器引擎 js解释器有哪些_面试_28

组成:

go 的javascript解释器引擎 js解释器有哪些_数组_29


window 对象是浏览器的顶级对象,它具有双重角色。

  1. 它是 JS 访问浏览器窗口的一个接口。
  2. 它是一个全局对象。定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法。

在调用的时候可以省略 window,对话框也属于 window 对象方法,如 alert()、prompt() 等。
注意:window下的一个特殊属性 window.name

12.2 window 对象的常见事件

12.2.1 窗口加载事件

窗口 (页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等), 就调用的处理函数。

window.onload = function(){}
或者 
window.addEventListener("load",function(){});

注意:

  1. 有了 window.onload 就可以把 JS 代码写到页面元素的上方,因为 onload 是等页面内容全部加载完毕,再去执行处理函数。
  2. window.onload 传统注册事件方式 只能写一次,如果有多个,会以最后一个 window.onload 为准。
  3. 如果使用 addEventListener 则没有限制
document.addEventListener('DOMContentLoaded',function(){})

DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。
Ie9以上才支持
如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded 事件比较合适。

12.2.2 调整窗口大小事件

window.onresize = function(){}

 window.addEventListener("resize",function(){});

注意:

  1. 只要窗口大小发生像素变化,就会触发这个事件。
  2. 经常利用这个事件完成响应式布局。 window.innerWidth 当前屏幕的宽度

12.3 定时器

window 对象提供了 2 个非常好用的方法-定时器。

  • setTimeout()
  • setInterval()

12.3.1 setTimeout() 定时器

window.setTimeout(调用函数, [延迟的毫秒数]);

window 可以省略。
延迟的毫秒数省略默认是 0,单位是毫秒。
因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。

12.3.2 停止 setTimeout() 定时器

//setInterval() 方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。
 window.clearTimeout(timeoutID)

clearTimeout()方法取消了先前通过调用 setTimeout() 建立的定时器。
里面的参数就是定时器的标识符 。

12.3.4 setInterval() 定时器

//setInterval() 方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。
 window.setInterval(回调函数, [间隔的毫秒数]);

window 可以省略。
延迟的毫秒数省略默认是 0,单位是毫秒。
因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。

12.3.5 停止setInterval() 定时器

window.clearInterval(intervalID);

clearInterval()方法取消了先前通过调用 setInterval()建立的定时器。
里面的参数就是定时器的标识符 。

12.4 JS执行队列

12.4.1 JS 是单线程

JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。于是,JS 中出现了同步和异步。

同步任务:
同步任务都在主线程上执行,形成一个执行栈。

异步任务:
JS 的异步是通过回调函数实现的。
一般而言,异步任务有以下三种类型:

  1. 普通事件,如 click、resize 等
  2. 资源加载,如 load、error 等
  3. 定时器,包括 setInterval、setTimeout 等

异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)。

12.4.2 JS 执行机制

  1. 先执行执行栈中的同步任务。
  2. 异步任务(回调函数)放入任务队列中。
  3. 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

go 的javascript解释器引擎 js解释器有哪些_前端_30


go 的javascript解释器引擎 js解释器有哪些_go 的javascript解释器引擎_31


由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( event loop)。

12.5 location 对象

window 对象给我们提供了一个 location 属性用于获取或设置窗体的 URL,并且可以用于解析 URL 。 因为这个属性返回的是一个对象,所以我们将这个属性也称为 location 对象。

12.5.1 URL

统一资源定位符 (Uniform Resource Locator, URL) 是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

URL 的一般语法格式为:

protocol://host[:port]/path/[?query]#fragment

http://www.baidu.cn/index.html?name=zhangsan&age=23#link

go 的javascript解释器引擎 js解释器有哪些_javascript_32

12.5.2 location 对象的属性

go 的javascript解释器引擎 js解释器有哪些_数组_33

12.5.3 location 对象的方法

go 的javascript解释器引擎 js解释器有哪些_面试_34

12.6 navigator 对象

navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。
下面前端代码可以判断用户那个终端打开页面,实现跳转

if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
    window.location.href = "";     //手机
 } else {
    window.location.href = "";     //电脑
 }

12.7 history 对象

window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的 URL。

go 的javascript解释器引擎 js解释器有哪些_go 的javascript解释器引擎_35

12.8 本地存储

随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。

本地存储特性:

  1. 数据存储在用户浏览器中
  2. 设置、读取方便、甚至页面刷新不丢失数据
  3. 容量较大,sessionStorage约5M、localStorage约20M
  4. 只能存储字符串,可以将对象JSON.stringify() 编码后存储

12.8.1 window.sessionStorage

  1. 生命周期为关闭浏览器窗口
  2. 在同一个窗口(页面)下数据可以共享
  3. 以键值对的形式存储使用
12.8.1.1 存储数据
sessionStorage.setItem(key, value)
12.8.1.2 获取数据
sessionStorage.getItem(key)
12.8.1.3 删除数据
sessionStorage.removeItem(key)
12.8.1.4 删除所有数据
sessionStorage.clear()

12.8.1 window.localStorage

  1. 声明周期永久生效,除非手动删除 否则关闭页面也会存在
  2. 可以多窗口(页面)共享(同一浏览器可以共享)
  3. 以键值对的形式存储使用
12.8.1.1 存储数据
localStorage.setItem(key, value)
12.8.1.2 获取数据
localStorage.getItem(key)
12.8.1.3 删除数据
localStorage.removeItem(key)
12.8.1.4 删除所有数据
localStorage.clear()

13 JS网页特效

13.1 元素偏移量 offset

offset 翻译过来就是偏移量, 我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小等。

  • 获得元素距离带有定位父元素的位置
  • 获得元素自身的大小(宽度高度)

注意: 返回的数值都不带单位

go 的javascript解释器引擎 js解释器有哪些_数组_36

offset 与 style 区别

go 的javascript解释器引擎 js解释器有哪些_面试_37

13.2 元素可视区 client

client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过 client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。

go 的javascript解释器引擎 js解释器有哪些_go 的javascript解释器引擎_38


go 的javascript解释器引擎 js解释器有哪些_javascript_39

13.3 元素滚动 scroll

scroll 翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。

go 的javascript解释器引擎 js解释器有哪些_数组_40


go 的javascript解释器引擎 js解释器有哪些_go 的javascript解释器引擎_41


如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件。

注意:页面滚动的距离通过 window.pageXOffset 获得

13.4 动画函数封装

13.4.1 动画实现原理

核心原理:通过定时器 setInterval() 不断移动盒子位置。
实现步骤:

  1. 获得盒子当前位置
  2. 让盒子在当前位置加上1个移动距离
  3. 利用定时器不断重复这个操作
  4. 加一个结束定时器的条件
  5. 注意此元素需要添加定位,才能使用element.style.left

13.4.2 动画函数简单封装

注意函数需要传递2个参数,动画对象和移动到的距离。

13.4.3 动画函数给不同元素记录不同定时器

如果多个元素都使用这个动画函数,每次都要var 声明定时器。我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。
核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性。

13.4.4 缓动效果原理

缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
思路:

  1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
  2. 核心算法: (目标值 - 现在的位置 ) / 10 做为每次移动的距离 步长
  3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
  4. 注意步长值需要取整

13.4.5 动画函数多个目标值之间移动

可以让动画函数从 800 移动到 500。
当我们点击按钮时候,判断步长是正值还是负值

  1. 如果是正值,则步长 往大了取整
  2. 如果是负值,则步长 向小了取整

13.4.6 动画函数添加回调函数

回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调。
回调函数写的位置:定时器结束的位置。

13.4.7 动画函数封装到单独JS文件里面

因为以后经常使用这个动画函数,可以单独封装到一个JS文件里面,使用的时候引用这个JS文件即可。

  1. 单独新建一个JS文件。
  2. HTML文件引入 JS 文件。

13.5 节流阀

防止轮播图按钮连续点击造成播放过快。
节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。
核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
开始设置一个变量 var flag = true;
If(flag) {flag = false; do something} 关闭水龙头
利用回调函数 动画执行完毕, flag = true 打开水龙头

14 JS移动端

14.1 触屏事件

14.1.1 概述

移动端浏览器兼容性较好,我们不需要考虑以前 JS 的兼容性问题,可以放心的使用原生 JS 书写效果,但是移动端也有自己独特的地方。比如触屏事件 touch(也称触摸事件),Android 和 IOS 都有。

touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作。

常见的触屏事件如下:

go 的javascript解释器引擎 js解释器有哪些_数组_42

14.1.2 触摸事件对象(TouchEvent)

TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少,等等

touchstart、touchmove、touchend 三个事件都会各自有事件对象。

触摸事件对象重点我们看三个常见对象列表:

go 的javascript解释器引擎 js解释器有哪些_go 的javascript解释器引擎_43

14.1.3 移动端拖动元素

  1. touchstart、touchmove、touchend 可以实现拖动元素
  2. 但是拖动元素需要当前手指的坐标值 我们可以使用 targetTouches[0] 里面的pageX 和 pageY
  3. 移动端拖动的原理: 手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离
  4. 手指移动的距离: 手指滑动中的位置 减去 手指刚开始触摸的位置

拖动元素三步曲:
(1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置
(2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子
(3) 离开手指 touchend:
注意: 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();

14.2 移动端常用开发插件

移动端常见插件:iScroll、Swiper、SuperSlider 。

Swiper 插件:
中文官网地址: https://www.swiper.com.cn/

iScroll 插件:
https://github.com/cubiq/iscroll

SuperSlider 插件:
http://www.superslide2.com/

视频插件 zy.media.js:
H5 给我们提供了 video 标签,但是浏览器的支持情况不同。在移动端我们可以使用插件方式来制作。

14.3 移动端click 延时解决方案

移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。
3种解决方案:

  1. 禁用缩放。 浏览器禁用默认的双击缩放行为并且去掉 300ms 的点击延迟。
<meta name="viewport" content="user-scalable=no">
  1. 利用touch事件自己封装这个事件解决 300ms 延迟。
    原理就是:
    1) 当我们手指触摸屏幕,记录当前触摸时间
    2) 当我们手指离开屏幕, 用离开的时间减去触摸的时间
    3) 如果时间小于150ms,并且没有滑动过屏幕, 那么我们就定义为点击
//封装tap,解决click 300ms 延时
function tap (obj, callback) {
        var isMove = false;
        var startTime = 0; // 记录触摸时候的时间变量
        obj.addEventListener('touchstart', function (e) {
            startTime = Date.now(); // 记录触摸时间
        });
        obj.addEventListener('touchmove', function (e) {
            isMove = true;  // 看看是否有滑动,有滑动算拖拽,不算点击
        });
        obj.addEventListener('touchend', function (e) {
            if (!isMove && (Date.now() - startTime) < 150) {  // 如果手指触摸和离开时间小于150ms 算点击
                callback && callback(); // 执行回调函数
            }
            isMove = false;  //  取反 重置
            startTime = 0;
        });
}
  //调用  
  tap(div, function(){   // 执行代码  });
  1. 使用插件。 fastclick 插件解决 300ms 延迟。
document.addEventListener('DOMContentLoaded',function () {
	/*等页面文档加载完成  不需要等所有的资源*/
	FastClick.attach(document.body);
});

14.4 移动端常用开发框架

Bootstrap、Vue(UniApp、Vant)、Angular

MUI 原生UI前端框架:
http://dev.dcloud.net.cn/mui/