JavaScript 学习笔记
JavaScript教程参考: https://wangdoc.com/javascript/index.html
1. 变量提升
console.log(a);
var a = 1;
var a;
console.log(a);
a = 1;
//输出undefined, a已声明, 但未赋值
2. 标识符
JavaScript 语言的标识符对大小写敏感
命名规则
- 第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号(
$
)和下划线(_
) - 第二个字符及后面的字符,除了 Unicode 字母、美元符号和下划线,还可以用数字
0-9
3. 数据类型(七种 ES6)
- 数值(number) : 整数和小数(比如
1
和3.14
) - 字符串(string):文本
- 布尔值(boolean):true / false
- undefined:表示“未定义”或不存在
- null:表示空值
- 对象(object):各种值组成的集合
- Symbol
4. 值类型
- typeof
- instanceof
- Object
.
prototype.
toString方法
5. 字符集
JavaScript 使用 Unicode 字符集
每个字符在 JavaScript 内部都是以16位(即2个字节)的 UTF-16 格式储存
6. Base64 转码
Base64 : 一种编码方法,可以将任意值转成 0~9、A~Z、a-z、+
和/
这64个字符组成的可打印字符
使用目的 : 为了不出现特殊字符,简化程序的处理。
使用场景 :
(1) 文本里面包含一些不可打印的符号,比如 ASCII 码0到31的符号都无法打印出来,这时可以使用 Base64 编码,将它们转成可以
打印的字符
(2) 需要以文本格式传递二进制数据,那么也可以使用 Base64 编码
相关方法 (不适合非 ASCII 码的字符,会报错) :
(1) btoa()
:任意值转为 Base64 编码
(2) atob()
:Base64 编码转为原来的值
要将非 ASCII 码字符转为 Base64 编码,必须中间插入一个转码环节,再使用这两个方法
function b64Encode(str) {
return btoa(encodeURIComponent(str));
}
function b64Decode(str) {
return decodeURIComponent(atob(str));
}
b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"
7. object对象
- 表达式 / 语句
({ foo: 123 }) // 正确 表达式
({ console.log(123) }) // 报错
{ console.log(123) } // 123 语句
- 属性操作
//赋值
var obj = {};
obj.foo = 'Hello';
obj['bar'] = 'World';
//读取
var obj = {
p: 'Hello World'
};
obj.p // "Hello World"
obj['p'] // "Hello World"
//查看 (Object.keys方法, 查看一个对象本身的所有属性)
var obj = {
key1: 1,
key2: 2
};
Object.keys(obj); // ['key1', 'key2']
//删除 (只能删除对象本身的属性,无法删除继承的属性)
var obj = { p: 1 };
Object.keys(obj) // ["p"]
delete obj.p // true
obj.p // undefined
Object.keys(obj) // []
//是否存在 (in运算符用于检查对象是否包含某个属性)
var obj = { p: 1 };
'p' in obj // true
'toString' in obj // true
//对象的hasOwnProperty方法判断是否为对象自身的属性
//遍历属性 (包含继承属性)
var obj = {a: 1, b: 2, c: 3};
for (var i in obj) {
console.log('键名:', i);
console.log('键值:', obj[i]);
}
// 键名: a
// 键值: 1
// 键名: b
// 键值: 2
// 键名: c
// 键值: 3
8. 函数
- 声明函数
(1) function 命令
function print(s) {
console.log(s);
}
(2) 函数表达式
var print = function(s) {
console.log(s);
};
/*
* 采用函数表达式声明函数时,function命令后面不带有函数名。如果加上函数名,该函数名只在函数体内部有
* 效,在函数体外部无效。
*/
var print = function x(){
console.log(typeof x);
};
x
// ReferenceError: x is not defined
print()
// function
//作用: (1) 可以在函数体内部调用自身
(2) 方便除错(除错工具显示函数调用栈时,将显示函数名,而不再显示这里是一个匿名函数)
(3) function 构造函数
var add = new Function(
'x',
'y',
'return x + y'
);
// 等同于
function add(x, y) {
return x + y;
}
-
arguments 对象
arguments
对象 : 可以在函数体内部读取所有参数
var f = function (one) {
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
}
f(1, 2, 3)
// 1
// 2
// 3
- 闭包
定义在一个函数内部的函数
作用 : (1) 读取外层函数内部的变量
(2) 让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在
(3) 封装对象的私有属性和私有方法
//闭包
function f1() {
var n = 999;
function f2() {
console.log(n);
}
return f2;
}
var result = f1();
result(); // 999
//变量保存在内存中
function createIncrementor(start) {
return function () {
return start++;
};
}
var inc = createIncrementor(5);
inc() // 5
inc() // 6
inc() // 7
/*
* start是函数createIncrementor的内部变量。通过闭包,start的状态被保留了,每一次调用都是在上一次 * 调用的基础上进行计算。从中可以看到,闭包inc使得函数createIncrementor的内部环境,一直存在。所 * 以,闭包可以看作是函数内部作用域的一个接口
*/
//封装对象的私有属性和私有方法
function Person(name) {
var _age;
function setAge(n) {
_age = n;
}
function getAge() {
return _age;
}
return {
name: name,
getAge: getAge,
setAge: setAge
};
}
var p1 = Person('张三');
p1.setAge(25);
p1.getAge() // 25
-
立即调用的函数表达式(IIFE)
根据 JavaScript 的语法,圆括号()
跟在函数名之后,表示调用该函数
var f = function f(){ return 1}();
f // 1
(function(){ /* code */ }());
// 或者
(function(){ /* code */ })();
9. 错误类型
Error
实例对象是最一般的错误类型,在它的基础上,JavaScript 还定义了其他6种错误对象
-
SyntaxError : 解析代码时发生的语法错误
-
ReferenceError : 引用一个不存在的变量时发生的错误
-
RangeError : 一个值超出有效范围时发生的错误
-
TypeError : 变量或参数不是预期类型时发生的错误
-
URIError : URI 相关函数的参数不正确时抛出的错误
-
EvalError : 函数没有被正确执行时 (该错误类型已经不再使用了,只是为了保证与以前代码兼容,才继续保留)
自定义错误 :
function UserError(message) {
this.message = message || '默认信息';
this.name = 'UserError';
}
UserError.prototype = new Error();
UserError.prototype.constructor = UserError;
//继承Error对象
10. JSON
类型和格式的规定 :
- 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象
- 原始类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和
null
(不能使用NaN
,Infinity
,-Infinity
和undefined
) - 字符串必须使用双引号表示,不能使用单引号
- 对象的键名必须放在双引号里面
- 数组或对象最后一个成员的后面,不能加逗号
JSON对象是 JavaScript 的原生对象,用来处理 JSON 格式数据。它有两个静态方法:JSON.stringify()
和JSON.parse()
-
JSON.stringify()
将一个值转为 JSON 字符串
(1)
忽略对象的不可遍历的属性
var obj = {};
Object.defineProperties(obj, {
'foo': {
value: 1,
enumerable: true
},
'bar': {
value: 2,
enumerable: false
}
});
JSON.stringify(obj); // "{"foo":1}"
(2)第二个参数
为数组时, 指定要转换为JSON的属性, 只对对象的属性有效
var obj = {
'prop1': 'value1',
'prop2': 'value2',
'prop3': 'value3'
};
var selectedProperties = ['prop1', 'prop2'];
JSON.stringify(obj, selectedProperties)
// "{"prop1":"value1","prop2":"value2"}"
为函数时, 用来更改返回值
function f(key, value) {
if (typeof value === "number") {
value = 2 * value;
}
return value;
}
JSON.stringify({ a: 1, b: 2 }, f)
// '{"a": 2,"b": 4}'
(3)第三个参数
用于增加返回的 JSON 字符串的可读性
// 默认输出
JSON.stringify({ p1: 1, p2: 2 })
// JSON.stringify({ p1: 1, p2: 2 })
// 分行输出
JSON.stringify({ p1: 1, p2: 2 }, null, '\t')
// {
// "p1": 1,
// "p2": 2
// }
(4)参数对象的 toJSON() 方法
如果参数对象有自定义的toJSON()
方法,那么JSON.stringify()
会使用这个方法的返回值作为参数,而忽略原对象的其他属性
var user = {
firstName: '三',
lastName: '张',
get fullName(){
return this.lastName + this.firstName;
},
toJSON: function () {
return {
name: this.lastName + this.firstName
};
}
};
JSON.stringify(user)
// "{"name":"张三"}"
JSON.parse() 将JSON字符串转换为对应的值
第二个参数:
function f(key, value) {
if (key === 'a') {
return value + 10;
}
return value;
}
JSON.parse('{"a": 1, "b": 2}', f)
// {a: 11, b: 2}
11. 实例对象
- 构造函数
JavaScript 语言使用构造函数(constructor)作为对象的模板。所谓”构造函数”,就是专门用来生成实例对象的函数
为了与普通函数区别,构造函数名字的第一个字母通常大写
- new命令
作用 : 执行构造函数,返回一个实例对象
var Vehicle = function () {
this.price = 1000;
};
var v = new Vehicle();
v.price // 1000
如果构造函数内部有return
语句,而且return
后面跟着一个对象,new
命令会返回return
语句指定的对象;否则,就会不管return
语
句,返回this
对象
var Vehicle = function (){
this.price = 1000;
return { price: 2000 };
};
(new Vehicle()).price
// 2000
- Object.create() 创建实例对象
以这个现有的对象作为模板,生成新的实例对象
var person1 = {
name: '张三',
age: 38,
greeting: function() {
console.log('Hi! I\'m ' + this.name + '.');
}
};
var person2 = Object.create(person1);
person2.name // 张三
person2.greeting() // Hi! I'm 张三.
- 原型对象(prototype)
原型对象的所有属性和方法,都能被实例对象共享
每个函数都有一个prototype
属性,指向一个对象。
function Animal(name) {
this.name = name;
}
Animal.prototype.color = 'white';
var cat1 = new Animal('大毛');
var cat2 = new Animal('二毛');
cat1.color // 'white'
cat2.color // 'white'
prototype
对象有一个constructor
属性,默认指向prototype
对象所在的构造函数
constructor
属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor
属性,防止引用的时
候出错
// 好的写法
C.prototype = {
constructor: C,
method1: function (...) { ... },
// ...
};
// 更好的写法
C.prototype.method1 = function (...) { ... };
/*
* 将constructor属性重新指向原来的构造函数,要么只在原型对象上添加方法,这样可以保证instanceof运算
* 符不会失真
*/
constructor
属性作用 :
(1) 可以得知某个实例对象,到底是哪一个构造函数产生的
function F() {};
var f = new F();
f.constructor === F // true
f.constructor === RegExp // false
(2)从一个实例对象新建另一个实例
function Constr() {}
var x = new Constr();
var y = new x.constructor();
y instanceof Constr // true
- 构造函数的继承
function Shape() {
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function (x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
};
// 第一步,子类继承父类的实例
function Rectangle() {
Shape.call(this); // 调用父类构造函数
}
// 另一种写法
function Rectangle() {
this.base = Shape;
this.base();
}
// 第二步,子类继承父类的原型
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
- 多重继承
JavaScript 不提供多重继承功能,即不允许一个对象同时继承多个对象。但是,可以通过变通方法,实现这个功能
function M1() {
this.hello = 'hello';
}
function M2() {
this.world = 'world';
}
function S() {
M1.call(this);
M2.call(this);
}
// 继承 M1
S.prototype = Object.create(M1.prototype);
// 继承链上加入 M2
Object.assign(S.prototype, M2.prototype);
// 指定构造函数
S.prototype.constructor = S;
var s = new S();
s.hello // 'hello'
s.world // 'world'
//子类S同时继承了父类M1和M2。这种模式又称为 Mixin(混入)
12. 异步操作
- 模式
(1) 回调函数
function f1(callback) {
// ...
callback();
}
function f2() {
// ...
}
f1(f2);
(2) 事件监听
//jQuery 的写法
f1.on('done', f2);
function f1() {
setTimeout(function () {
// ...
f1.trigger('done');
}, 1000);
}
//f1.trigger('done')表示,执行完成后,立即触发done事件,从而开始执行f2
(3) 发布/订阅
jQuery.subscribe('done', f2);
function f1() {
setTimeout(function () {
// ...
jQuery.publish('done');
}, 1000);
}
jQuery.unsubscribe('done', f2);
- 定时器
(1) setTimeout(func | code, delay, param...)
func | code 执行函数/代码, delay 推迟执行的毫秒数, param 回调函数参数, 执行一次
指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器
如果回调函数是对象的方法,那么setTimeout
使得方法内部的this
关键字指向全局环境,而不是定义时所在的那个对象
(2) setInterval(func | code, interval, param...)
func | code 执行函数/代码, 间隔interval毫秒数执行一次, param 回调函数参数, 无限次执行
由于不考虑每次任务执行本身所消耗的时间。因此实际上,两次执行之间的间隔会小于指定的时间
为了确保两次执行之间有固定的间隔,可以不用setInterval
,而是每次执行结束后,使用setTimeout
指定下一次执行的具
体时间
(3) clearTimeout(TimerId),clearInterval(TimerId)
取消对应定时器
(4) setTimeout(f, 0)
尽可能早地执行f
,但是并不能保证立刻就执行f
-
Promise
对象
异步操作解决方案,为异步操作提供统一接口。它起到代理作用(proxy),充当异步操作与回调函数之间的中介,使得异步操作具
备同步操作的接口
(1) 对象状态
异步操作未完成(pending), 成功(fulfilled), 失败(rejected)
(2) 基本用法
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
构造函数接受一个函数作为参数,该函数的两个参数分别是resolve
和reject
。它们是两个函数,由 JavaScript 引擎提供
resolve
函数的作用是,将Promise
对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并
将异步操作的结果,作为参数传递出去
reject
函数的作用是,将Promise
对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将
异步操作报出的错误,作为参数传递出去
then() 方法
指定resolved
状态和rejected
状态的回调函数
可以接受两个回调函数作为参数。第一个回调函数是状态变为resolved
时调用,第二个回调函数是状态变为rejected
时调用。这两
个函数都是可选的,不一定要提供。它们都接受Promise
对象传出的值作为参数
promise.then(function(value) {
// success
}, function(error) {
// failure
});
catch() 方法
是then(null, rejection)
或.then(undefined, rejection)
的别名,用于指定发生错误时的回调函数, 推荐第二种写法
// bad
promise
.then(function(data) {
// success
}, function(err) {
// error
});
// good
promise
.then(function(data) { //cb
// success
})
.catch(function(err) {
// error
});
finally() 方法
不管 Promise 对象最后状态如何,都会执行的操作
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
all() 方法
将多个 Promise 实例,包装成一个新的 Promise 实例
const p = Promise.all([p1, p2, p3]);
只有p1
、p2
、p3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时p1
、p2
、p3
的返回值组成一个数组,传递给p
的回调函
数
只要p1
、p2
、p3
之中有一个被rejected
,p
的状态就变成rejected
,此时第一个被reject
的实例的返回值,会传递给p
的回调函数
注意,如果作为参数的 Promise 实例,自己定义了catch
方法,那么它一旦被rejected
,并不会触发Promise.all()
的catch
方法
any() 方法
将多个 Promise 实例,包装成一个新的 Promise 实例
const p = Promise.any([p1, p2, p3]);
只要p1
、p2
、p3
的状态有一个变成fulfilled
,p
的状态就会变成fulfilled
只有p1
、p2
、p3
的状态都变成rejected
,p
的状态就变成rejected
抛出的错误为AggregateError 实例。它相当于一个数组,每个成员对应一个被rejected
的操作所抛出的错误
var resolved = Promise.resolve(42);
var rejected = Promise.reject(-1);
var alsoRejected = Promise.reject(Infinity);
Promise.any([resolved, rejected, alsoRejected]).then(function (result) {
console.log(result); // 42
});
Promise.any([rejected, alsoRejected]).catch(function (results) {
console.log(results); // [-1, Infinity]
});
race() 方法
将多个 Promise 实例,包装成一个新的 Promise 实例
const p = Promise.race([p1, p2, p3]);
只要p1
、p2
、p3
之中有一个实例率先改变状态,p
的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p
的回调函
数
const p = Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p
.then(console.log)
.catch(console.error);
//如果 5 秒之内fetch方法无法返回结果,变量p的状态就会变为rejected,从而触发catch方法指定的回调函数
allSettled() 方法
不关心异步操作的结果,只关心这些操作有没有结束
const promises = [
fetch('/api-1'),
fetch('/api-2'),
fetch('/api-3'),
];
await Promise.allSettled(promises);
removeLoadingIndicator();
//对服务器发出三个请求,等到三个请求都结束,不管请求成功还是失败,加载的滚动图标就会消失
resolve()方法
将现有对象转为 Promise 对象
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
参数 :
Promise实例 : 不做任何修改, 返回实例
thenable对象 :
thenable
对象指的是具有then
方法的对象
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function (value) {
console.log(value); // 42
});
不具有then方法的对象或不是对象 : 返回一个新的 Promise 对象,状态为resolved
不带有参数 :
直接返回一个resolved
状态的 Promise 对象
reject() 方法
返回一个新的 Promise 实例,该实例的状态为rejected
try() 方法
不区分同步/异步函数, 统一使用
Promise 处理, then指定下一步操作, catch处理异常
13. DOM
DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个 JavaScript
对象,从而可以用脚本进行各种操作(比如增删内容)
- 节点
DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM 树),就是由各种不同类型的节点组成。每个节点可以看作是文
档树的一片叶子
(1) Document
:整个文档树的顶层节点
(2) DocumentType
:doctype
标签(比如<!DOCTYPE html>
)
(3) Element
:网页的各种HTML标签(比如<body>
、<a>
等)
(4) Attr
:网页元素的属性(比如class="right"
)
(5) Text
:标签之间或标签包含的文本
(6) Comment
:注释
(7) DocumentFragment
:文档的片段
- 节点树
浏览器原生提供document
节点,代表整个文档。
文档的第一层有两个节点,第一个是文档类型节点(<!doctype html>
),第二个是 HTML 网页的顶层容器标签<html>
。后者构成了
树结构的根节点(root node),其他 HTML 标签节点都是它的下级节点
除了根节点,其他节点都有三种层级关系 :
(1) 父节点关系(parentNode):直接的那个上级节点
(2) 子节点关系(childNodes):直接的下级节点
(3) 同级节点关系(sibling):拥有同一个父节点的节点
- Node接口
所有 DOM 节点对象都继承了 Node 接口,拥有一些共同的属性和方法
(1)属性
nodeType 节点的类型
nodeName 节点名称
nodeValue 节点的文本值
baseURI 当前绝对路径
ownerDocument 当前节点所在的顶层文档对象
nextSibling 紧跟在当前节点后面的第一个同级节点
childNodes 当前节点所有子节点
(2)方法
appendChild() 接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点
hasChildNodes() 当前节点是否有子节点
- NodeList接口
能够容纳多个节点, 可以包含各种类型的节点
- HTMLCollection接口
能够容纳多个节点, 只能包含 HTML 元素节点
- ParentNode 接口
当前节点是一个父节点,提供一些处理子节点的方法
只有元素节点(element)、文档节点(document)和文档片段节点(documentFragment)拥有子节点,因此只有这三类节点会拥
有ParentNode
接口
(1)属性
children 返回一个HTMLCollection
实例,成员是当前节点的所有元素子节点。该属性只读
firstElementChild 返回当前节点的第一个元素子节点
lastElementChild 返回当前节点的最后一个元素子节点
childElementCount 返回一个整数,表示当前节点的所有元素子节点的数目
(2)方法
append() 为当前节点追加一个或多个子节点,位置是最后一个元素子节点的后面
prepend() 为当前节点追加一个或多个子节点,位置是第一个元素子节点的前面
- ChildNode 接口
如果一个节点有父节点,那么该节点就拥有了ChildNode
接口
方法
remove() 从父节点移除当前节点
before() 在当前节点的前面,插入一个或多个同级节点
after() 在当前节点的后面,插入一个或多个同级节点
replaceWith() 使用参数节点,替换当前节点
-
Document 节点
代表整个文档,每张网页都有自己的document
对象
window.document
属性就指向这个对象。只要浏览器开始载入 HTML 文档,该对象就存在了,可以直接使用
document
对象继承了EventTarget
接口和Node
接口,并且混入(mixin)了ParentNode
接口。这意味着,这些接口的方法都可以在
document
对象上调用
(1)获取document
对象
正常的网页,直接使用document
或window.document
iframe
框架里面的网页,使用iframe
节点的contentDocument
属性
Ajax 操作返回的文档,使用XMLHttpRequest
对象的responseXML
属性
内部节点的ownerDocument
属性
(2)属性
scrollingElement 返回文档的滚动元素
activeElement 返回获得当前焦点(focus)的 DOM 元素
fullscreenElement 返回当前以全屏状态展示的 DOM 元素
links 返回当前文档所有设定了href
属性的<a>
及<area>
节点
forms 返回所有<form>
表单节点
images 返回页面所有<img>
图片节点
documentURI / URL 返回当前文档的网址
domain 返回当前文档的域名
location 浏览器提供的原生对象
hidden 当前页面是否可见 窗口最小化、浏览器切换了 Tab,都会导致导致页面不可见
visibilityState 返回文档的可见状态 visible / hidden / prerender / unloaded
readyState 返回当前文档的状态 loading / interactive / complete
(3)方法
open() 清除当前文档所有内容,使得文档处于可写状态
write() 写入内容
close() 关闭文档
getElementsByTagName() 搜索 HTML 标签名,返回符合条件的元素
getElementsByClassName() class
名字符合指定条件的元素
getElementsByName() 选择拥有name
属性的 HTML 元素
getElementById() 返回匹配指定id
属性的元素节点
createElement() 生成元素节点
createEvent() 生成一个事件对象
hasFocus() 是否有元素被激活或获得焦点
- Element 节点
Element
节点对象对应网页的 HTML 元素。每一个 HTML 元素,在 DOM 树上都会转化成一个Element
节点对象
继承了Node
接口,因此Node
的属性和方法在Element
对象都存在
(1)属性
accessKey 读写分配给当前元素的快捷键
draggable 当前元素是否可拖动
lang 当前元素的语言设置
hidden 当前元素是否可见, 只在 CSS 没有明确设定当前元素的可见性时才有效
contentEditable 使得元素的内容可以编辑
attributes 当前元素节点的所有属性节点
dataset 返回一个对象,可以从这个对象读写data-
属性(自定义)
innerHTML 该元素包含的所有 HTML 代码
outerHTML 该元素包含的所有 HTML 代码, 包括该元素本身和所有子元素
(2)方法
getAttribute() 读取某个属性的值
getAttributeNames() 返回当前元素的所有属性名
setAttribute() 写入属性值
hasAttribute() 某个属性是否存在
hasAttributes() 当前元素是否有属性
removeAttribute() 删除属性
getElementsByClassName() 具有指定 class 的子元素节点
getElementsByTagName() 匹配指定标签名的子元素节点
addEventListener() 添加事件的回调函数
removeEventListener() 移除事件监听函数
dispatchEvent() 触发事件
getBoundingClientRect() 返回一个对象,提供当前元素节点的大小、位置等信息,基本上就是 CSS 盒状模型的所有信息
insertAdjacentElement() 相对于当前元素的指定位置,插入一个新的节点
focus() 将当前页面的焦点,转移到指定元素上
blur() 用于将焦点从当前元素移除
click() 相当于触发了click事件
- Text 节点
代表元素节点(Element
)和属性节点(Attribute
)的文本内容
(1)属性
data 设置或读取文本节点的内容
length 当前文本节点的文本长度
nextElementSibling 当前文本节点后面的那个同级元素节点
previousElementSibling 当前文本节点前面最近的同级元素节点
(2)方法
appendData() 追加字符串
deleteData() 删除子字符串, 第一个参数为子字符串开始位置,第二个参数为子字符串长度
insertData() 插入字符串, 第一个参数为插入位置,第二个参数为插入的子字符串
replaceData() 用于替换文本,第一个参数为替换开始位置,第二个参数为需要被替换掉的长度,第三个参数为新加入的字符串
subStringData() 用于获取子字符串,第一个参数为子字符串在Text
节点中的开始位置,第二个参数为子字符串长度
remove() 移除当前Text节点
- DocumentFragment 节点
代表一个文档的片段,本身就是一个完整的 DOM 树形结构。它没有父节点,parentNode
返回null
,但是可以插入任意数量的子节
点。它不属于当前文档,操作DocumentFragment
节点,要比直接操作 DOM 树快得多
var docFrag = document.createDocumentFragment();
// 等同于
var docFrag = new DocumentFragment();
var li = document.createElement('li');
li.textContent = 'Hello World';
docFrag.appendChild(li);
document.querySelector('ul').appendChild(docFrag);
- Mutation Observer API
监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知
(1) 与事件对比
事件 : 同步触发, DOM变动会立即出发相应的事件
Mutation Observer : 异步触发, 等到当前所有 DOM 操作都结束才触发
(2) 特点
等待所有脚本任务完成后,才会运行(即异步触发方式)
DOM 变动记录封装成一个数组进行处理,而不是一条条个别处理 DOM 变动
可以观察 DOM 的所有类型变动,也可以指定只观察某一类变动
(3) 构造函数
可指定回调函数, 接受两个参数, 第一个是变动数组,第二个是观察器实例
(4) 实例方法
observe() 启动监听
参数1:所要观察的 DOM 节点
参数2: 所要观察的特定变动 变动类型(childList / attributes / characterData)
var article = document.querySelector('article');
var options = {
'childList': true,
'attributes':true
} ;
observer.observe(article, options);
disconnect() 停止观察
takeRecords() 清除变动记录
(5) MutationRecord 对象
DOM 每次发生变化,就会生成一条变动记录(MutationRecord 实例)。该实例包含了与变动相关的所有信息
14. 事件
- EventTarget 接口
DOM 的事件操作(监听和触发),都定义在EventTarget
接口。所有节点对象都部署了这个接口
实例方法:
addEventListener() 绑定事件监听函数
参数1 : 事件名称
参数2 : 监听函数或具有handleEvent函数的对象
参数3 : 布尔值,表示监听函数是否在捕获阶段(capture)触发, 或者, 为配置对象(capture, once 监听函数是否只触发一次
passive 监听函数不会调用事件的preventDefault
方法)
removeEventListener() 移除事件监听函数, 参数与addEventListener方法一致
dispatchEvent() 触发指定事件, 参数为Event对象实例
- 事件模型
浏览器的事件模型,就是通过监听函数(listener)对事件做出反应。事件发生后,浏览器监听到了这个事件,就会执行对应的监听
函数。这是事件驱动编程模式(event-driven)的主要编程方式
绑定事件监听函数 :
(1)HTML的on属性
属性值为执行的代码, 不是函数, 只会在冒泡阶段触发
(2)元素节点的事件属性
值为函数名, 只会在冒泡阶段触发
(3)addEventListener()方法
事件的传播 :
一个事件发生后,会在子元素和父元素之间传播(propagation)。这种传播分成三个阶段
第一阶段: 从window
对象传导到目标节点(上层传到底层),称为“捕获阶段”(capture phase)
第二阶段: 在目标节点上触发,称为“目标阶段”(target phase)
第三阶段: 从目标节点传导回window
对象(从底层传回上层),称为“冒泡阶段”(bubbling phase)
事件的代理 : 由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处
理多个子元素的事件。这种方法叫做事件的代理(delegation)
- Event 对象
事件发生以后,会产生一个事件对象,作为参数传给监听函数。浏览器原生提供一个Event
对象,所有的事件都是这个对象的实例
(1)参数
参数1 : 事件名称
参数2 : 配置对象(bubbles, 默认false, 事件对象是否冒泡, cancelable, 默认false, 是否可取消)
(2)属性
bubbles: 是否会冒泡
eventPhase: 事件目前所处的阶段 (0 事件未发生 1 处于捕获阶段 2 到达目标节点 3 处于冒泡阶段)
cancelable: 是否可以取消
target: 触发事件的节点
isTrusted: 是否由用户产生
detail: 只有浏览器的 UI (用户界面)事件才具有。该属性返回一个数值,表示事件的某种信息。具体含义与事件类型相关
(3)方法
preventDefault() : 取消浏览器对当前事件的默认行为
stopPropagation() : 阻止事件在 DOM 中继续传播,防止再触发定义在别的节点上的监听函数,但是不包括在当前节点上其他的
事件监听函数
stopImmediatePropagation() : 阻止同一个事件的其他监听函数被调用,不管监听函数定义在当前节点还是其他节点。也就是说,
该方法阻止事件的传播,比Event.stopPropagation()
更彻底
- 鼠标事件
(1)种类
click : 按下鼠标(通常是按下主按钮)时触发
dblclick : 在同一个元素上双击鼠标时触发
mousedown : 按下鼠标键时触发
mouseup : 释放按下的鼠标键时触发
mousemove : 在一个节点内部移动时触发
wheel : 滚动鼠标的滚轮时触发
(2)MouseEvent 接口
构造函数接受两个参数, 参数1事件类型, 参数2配置对象
属性 :
altKey / ctrlKey / metaKey / shiftKey 是否按下对应键
button 按下了鼠标哪个键 (0 左键或没有初始化这个属性 1 中间/滚轮 2 右键)
buttons 同时按下哪个键 , 返回二进制和(1 左键 2 右键 4 中键)
方法 :
getModifierState() 判断有没有按下特定的功能键
(3)WheelEvent 接口
鼠标滚轮事件的实例对象, 浏览器原生提供WheelEvent()
构造函数,用来生成WheelEvent
实例
- 键盘事件
(1)种类
keydown : 按下键盘触发
keypress : 按下有值的键触发, 不包括( Ctrl、Alt、Shift、Meta), 有值键先触发keydown事件, 再触发本事件
keyup : 松开键盘时触发
(2)KeyboardEvent 接口
构造函数接受两个参数, 参数1事件类型, 参数2配置对象
属性 :
code 返回一个字符串,表示当前按下的键的字符串形式
key 返回一个字符串,表示按下的键名
location 返回一个整数,表示按下的键处在键盘的哪一个区域
repeat 返回一个布尔值,代表该键是否被按着不放,以便判断是否重复这个键
方法 :
getModifierState() 判断有没有按下特定的功能键
- 进度事件
(1)种类
abort 外部资源中止加载时(比如用户取消)触发
error 由于错误导致外部资源无法加载时触发
load 加载成功时触发
loadstart 开始加载时触发
loadend 停止加载时触发
progress 加载过程中不断触发
timeout 加载超时触发
(2)ProgressEvent 接口
构造函数接受两个参数, 参数1事件类型, 参数2配置对象
配置项 :
lengthComputable 布尔值,表示加载的总量是否可以计算,默认是false
loaded 整数, 表示已加载的量
total 整数, 表示需要加载的总量
- 表单事件
(1)种类
input事件 值发生变化时触发
select事件 选中文本时触发
change事件 失去焦点时触发
invalid事件 表单元素的值不满足校验条件触发
reset事件 表单重置
submit事件 表单提交
(2)InputEvent 接口
构造函数接受两个参数, 参数1事件名称, 参数2配置对象
属性 :
data 返回字符串, 表示变动的内容
inputType 返回字符串, 表示发生变更的类型(insertText / insertFromPaste)
dataTransfer 接受粘贴内容或拖拽内容时有效
- 触摸事件
(1)种类
touchstart 开始触摸时触发
touchend 不再接触屏幕时触发
touchmove 移动触摸点时触发
touchcancel 触摸点取消时触发
(2)Touch 接口
代表单个触摸点
构造函数接受一个配置对象参数
属性 :
identifier 返回整数, 表示触摸点唯一ID
force 0 无压力 1 硬件识别的最大压力
target 返回一个元素节点, 触摸发生时所在的元素节点
(3)TouchList 接口
代表一组触摸点的集合
通过TouchEvent.touches
、TouchEvent.changedTouches
、TouchEvent.targetTouches
这几个属性获取
length属性, 表示成员数量
item()方法, 返回指定位置的成员, 参数为位置编号
(4)TouchEvent 接口
构造函数接受两个参数, 参数1事件类型, 参数2配置对象
属性 :
changedTouches 返回TouchList实例, 本次触摸事件的触摸点
touches 返回TouchList实例, 仍然处于活动状态的触摸点
targetTouches 返回TouchList实例, 触摸事件目标元素节点内部, 处于活动的触摸点
- 拖拉事件
(1)DragEvent 接口
拖拉事件都继承DragEvent接口
构造函数接受两个参数, 参数1事件类型, 参数2配置对象
(2)DataTransfer 接口
拖拉事件的实例有一个dataTransfer属性, 读写需要传递的数据
属性 :
dropEffect : 设置被拖拉节点时的效果
effectAllowed : 本次拖拉中允许的效果
files : 一组本地文件
types : 拖拉的数据格式
方法 :
setData() 设置拖拉事件的数据
getData() 返回指定类型的数据
clearData() 删除事件所带指定类型的数据
setDragImage() 自定义拖动时图片
- 资源事件
beforeunload 资源将要卸载前触发
unload 窗口关闭或者document对象将要卸载时触发
load 页面或资源加载成功时触发, 从缓存中加载不会触发
error 页面或资源加载失败时触发
- session 历史事件
pageshow 页面加载时触发(persisted属性 false为第一次加载, true为从缓存中加载)
pagehide 离开当前页面触发(persisted属性 false不保存在缓存中, true保存在缓存中)
popstate history对象的当前记录发生显式切换时触发
hashchange URL的hash部分发生变化时触发
- 网页状态事件
DOMContentLoaded 网页下载解析完成后触发, 比load事件早
readystatechange 当 Document 对象和 XMLHttpRequest 对象的readyState
属性发生变化时触发(loading / interactive / complate)
- 窗口事件
scroll 在文档或文档元素滚动时触发
resize 改变浏览器窗口时触发
fullscreenchange 进入/退出全屏时触发
fullscreenerror 无法切换到全屏时触发
- 剪贴板事件
cut 将选中的内容从文档中移除,加入剪贴板时触发
copy 复制动作时触发
paste 剪贴板内容粘贴到文档后触发
- 焦点事件
focus 获得焦点后触发,该事件不会冒泡
blur 失去焦点后触发,该事件不会冒泡
focusin 将要获得焦点时触发,发生在focus
事件之前。该事件会冒泡
focusout 将要失去焦点时触发,发生在blur
事件之前。该事件会冒泡
- CustomEvent 接口
用于生成自定义的事件实例
如果需要在触发事件的同时,传入指定的数据,就可以使用 CustomEvent 接口生成的自定义事件对象
构造函数接受两个参数, 参数1事件名称, 参数2配置对象(detail 事件附带数据)
- GlobalEventHandlers 接口
只能为每个事件指定一个回调函数,并且无法指定事件触发的阶段
各种 HTML 元素、document
对象、window
对象上面都可以使用GlobalEventHandlers
接口提供的属性
属性 :
onabort 停止加载发生时触发, 一般只用在<img>元素上
onerror JavaScript 的运行时错误, 触发window.onerror() / 资源加载错误, 触发元素的onerror属性
onload 元素完成加载时触发, window对象所有资源加载完成触发 / <img><video> 加载开始时, 触发onloadstart
onfocus 获得焦点触发
onblur 失去焦点时触发
onscroll 页面元素滚动时触发
oncontextmenu 按下右键触发, 返回false禁止右键菜单
onshow 右键菜单显示时触发
15. 浏览器模型
- 概述
嵌入网页的方法 :
(1)<script> 元素直接嵌入代码
(2)<script> 标签加载外部脚本(integrity属性, 写入hash签名, 验证脚本一致性)
(3)事件属性 网页元素的事件属性(onclick), 可以写入JavaScript 代码
(4)URL协议 URL支持javascript: 协议, 在URL的位置写入代码, 使用的时候即执行
建议 : <script>
标签都放在页面底部, 防止外部脚本加载时间长, 造成页面假死状态
正常网页加载流程 :
(1)浏览器一边下载 HTML 网页,一边开始解析
(2)解析过程中,浏览器发现<script>
元素,就暂停解析,把网页渲染的控制权转交给 JavaScript 引擎
(3)如果<script>
元素引用了外部脚本,就下载该脚本再执行,否则就直接执行代码
(4)JavaScript 引擎执行完毕,控制权交还渲染引擎,恢复往下解析 HTML 网页
defer属性(保证执行顺序)
解决脚本文件下载阻塞网页渲染的问题, 延迟脚本执行, 等到DOM加载生成后, 再执行
async属性
解决脚本文件下载阻塞网页渲染的问题, 使用另一个进程下载脚本, 下载时不会阻塞渲染
脚本的动态加载
['a.js', 'b.js'].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
动态生成不会造成浏览器假死, async设为false, 即可保证执行顺序
- window对象
指当前浏览器窗口, 也是当前页面顶层对象, 一个变量未声明, 默认为顶层对象的属性
对象属性 :
name 当前浏览器窗口的名称
closed 窗口是否关闭
opener 打开当前窗口的父窗口
self / window 指向窗口本身
frames 页面内所有框架窗口, 实际上是window对象的别名
length 当前网页包含框架总数
组件属性(visible 是否可见) :
locationbar 地址栏对象
menubar 菜单栏对象
scrollbars 窗口的滚动条对象
toolbar 工具栏对象
statusbar 状态栏对象
personalbar 用户安装的 个人工具栏对象
全局对象属性 :
location 获取当前窗口的URL信息
navigator 获取环境信息
history 浏览器历史
localStorage 本地存储的localStorage数据
sessionStorage 本地存储的sessionStorage数据
console 操作控制台
screen 屏幕信息
方法 :
alert() 通知信息
prompt() 获取用户输入信息
confirm() 征询用户是否同意
open() 新建新窗口
close() 关闭当前窗口
stop() 停止加载图像, 视频
moveTo() 移动窗口到指定位置
moveBy() 移动窗口到相对位置
scrollTo() 将文档滚动到指定位置
scrollBy() 将网页滚动指定距离
print() 弹出打印对话框
focus() 激活窗口, 获得焦点
blur() 将焦点从窗口移除
getSelection() 返回Selection对象, 表示选中的文本
requestAnimationFrame() 推迟到浏览器下一次重流时执行
requestIdleCallback() 推迟到系统资源空闲时执行
- Navigator 对象
指向一个包含浏览器和系统信息的 Navigator 对象
属性 :
userAgent 浏览器的厂商和版本信息
plugins 浏览器安装的插件
platform 用户的操作系统信息
onLine 在线 / 离线, 在线触发online事件, 离线触发onoffline事件
language 浏览器首选语言
languages 用户可以接受的语言
geolocation 用户地理位置信息
cookieEnabled cookie功能是否打开
connection 当前网络连接的相关信息
sendBeacon()方法 异步发出请求, 参数1目标服务器URL, 参数2发送的数据
- Cookie
服务器保存在浏览器的一小段文本信息,一般大小不能超过4KB。浏览器每次向服务器发出请求,就会自动附上这段信息
元数据(名称, 值, 过期时间, 所属域名, 生效的路径)
用途 :
保存登录、购物车等需要记录的信息
保存用户的偏好,比如网页的字体大小、背景色等
记录和分析用户行为
生成 :
服务器如果希望在浏览器保存 Cookie,就要在 HTTP 回应的头信息里面,放置一个Set-Cookie
字段
发送 :
使用 HTTP 头信息的Cookie
字段
属性 :
Expires 指定具体的到期时间, 不设置, 则只在当前会话有效, 关闭窗口, 即删除
Max-Age 从现在开始, Cookie存在的秒数, 优先生效
Domain 哪些域名需要附带cookie, 不设置, 当前域名
Path 哪些路径需要附带cookie, 前提域名一致
Secure 加密协议HTTPS下附带, 通信为HTTPS协议自动打开
HttpOnly 指定该 Cookie 无法通过 JavaScript 脚本拿到
SameSite 限制第三方cookie (Strict , Lax , None)
删除一个现存 Cookie 的唯一方法,是设置它的expires
属性为一个过去的日期
- 同源限制
同源 : 协议 / 域名 / 端口 相同
目的 : 保证用户信息的安全,防止恶意的网站窃取数据
非同源限制范围 :
无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
无法接触非同源网页的 DOM
无法向非同源地址发送 AJAX 请求
规避限制 :
cookie 设置document.domain, 共享cookie
片段识别符 URL的#号后的部分, 可以把信息写入父/子窗口的片段标识符
window.postMessage 允许跨窗口通信, 不论是否同源, 参数1信息内容, 参数2URL地址或*向所有窗口发送
LocalStorage 子窗口将父窗口发来的消息, 写入自己的LocalStorage
JSONP 服务器与客户端跨源通信常用方法, 没有兼容问题, 只能发GET请求
WebSocket 支持跨源通信
CORS 跨源资源分享, 跨源AJAX请求根本解决方法, 允许任何类型请求
- CORS通信
跨源资源分享, 允许浏览器向跨域的服务器,发出XMLHttpRequest
请求,从而克服了 AJAX 只能同源使用的限制
简单请求
条件 :
(1)请求方法为HEAD, GET , POST
(2)HTTP头信息不超出以下字段(Accept, Accept-Language, Content-Language, Last-Event-ID, Content-Type限三个值)
流程 :
请求头信息添加Origin字段
响应头Access-Control-Allow-Origin, 为请求时Origin值或为*, 即在许可范围内
非简单请求
正式通信前, 先发起OPTIONS预请求, 询问服务器当前域名是否在许可名单中, 以及支持哪些HTTP方法和头信息字段
- Storage 接口
用于脚本在浏览器保存数据, 以键值对的形式存储
sessionStorage 保存的数据用于浏览器的一次会话, 会话结束, 数据清空
localStorage 保存的数据长期存在
length属性 保存数据项的个数
方法 :
setItem() 存入数据, 参数1键名, 参数2值
getItem() 读取数据, 参数键名
removeItem() 清除指定键名
clear() 清除所有保存的数据
存储的数据方法变化时, 触发storage事件
- History 对象
当前窗口的浏览历史
属性 :
length 当前窗口访问过的网址数量
state History 堆栈最上层的状态值
方法 :
back() 移动到上一个网址
forward() 移动到下一个网址
go() go(1)相当于forward(), go(-1) 相当于back()
pushState() 在历史中添加一条记录
同一个文档的浏览历史出现变化时, 触发popstate事件
- Location 对象
提供 URL 相关的信息和操作方法
属性 :
href 整个URL, 写入新的URL地址, 会立刻跳转
protocol 当前URL的协议
pathname URL的路径部分
search 查询字符串部分, 从问号开始
hash 片段字符串部分
origin URL协议, 主机名, 端口
方法 :
assign() 接受URL字符串为参数, 立刻跳转
replace() 作用同上, 会在浏览历史删除当前网址
reload() 重新加载当前网址
- URL 对象
JavaScript 提供四个 URL 的编码/解码方法
encodeURI() 转码整个URL
encodeURIComponent 转码URL组成部分, 包括元字符
decodeURI() 解码整个URL
decodeURIComponent() 解码URL片段
实例属性与Location对象属性基本一致
URL.createObjectURL() 为上传/下载的文件 ,流媒体文件生成一个URL字符串, 代表File对象或Blob对象的URL
URL.revokeObjectURL() 释放上一个方法生成的URL实例
URLSearchParams 解析处理URL的查询字符串, 问号后面的部分
- ArrayBuffer 对象
操作内存
- Blob 对象
操作二进制文件
- File 对象
构造函数接受三个参数, 参数1数组, 文件内容, 参数2文件名, 参数3配置对象(type, MIME类型, lastModified 时间戳, 上次修改时间)
属性 :
lastModified 最后修改时间
name 文件名或文件路径
size 文件大小
type 文件的MIME类型
- FileReader 对象
读取File对象或Blob对象所包含的文件内容
- FormData 对象
通过脚本构造/编辑表单, 发送至服务器
表单属性 :
novalidate 关闭浏览器的自动校验
enctype 编码格式
GET方法 该属性无效, 以URL的查询字符串发出
POST方法 默认以application/x-www-form-urlencoded格式发送
text/plain 以纯文本格式发送
multipart/form-data 混合格式发送
方法 :
get() 获取指定键名对应的值
set() 设置指定键名的值
delete() 删除指定键名
append() 添加一个键值对
has() 是否有指定键名
keys() 用于遍历所有键名
values() 用于遍历所有键值
entries() 用于遍历键值对
数据校验 :
required / minlength / maxlength / min / max
控件通过验证, 匹配到:valid的CSS伪类; 没通过验证, 匹配到:invalid的CSS伪类
checkValidity() 手动触发校验, true通过校验
setCustomValidity() 自定义校验失败时的报错信息
willValidate属性 该控件是否会在提交时进行校验
validationMessage属性 返回字符串, 没通过校验时, 浏览器提示文本
validity属性 返回ValidityState对象, 包含当前校验状态的信息
- IndexedDB
浏览器提供的本地数据库
特点 :
键值对存储 对象仓库中, 数据以键值对的形式保存
异步 不会锁死浏览器
支持事务 失败即回滚
同源限制 每一个数据库对应创建它的域名, 网页只能访问自身域名下的数据库
存储空间大 一般不少于250M
支持二进制存储
概念 :
数据库 IDBDatabase 对象 , 相关数据的容器
对象仓库 IDBObjectStore 对象, 每个数据库包含若干对象仓库, 类似关系型数据库表格
索引 IDBIndex 对象, 加速数据检索
事务 IDBTransaction 对象, 提供error, abort, complete事件
操作请求 IDBRequest 对象
指针 IDBCursor 对象
主键集合 IDBKeyRange 对象
- Web Worker
作用 : 创建多线程环境, 允许主线程创建Worker线程
属性/方法 :
name worker名称, 由构造函数指定
onmessage 指定message事件监听函数
onmessageerror 发送的数据无法序列化成字符串时, 触发
close() 关闭worker线程
postMessage() 向产生这个worker的线程发送消息
importScripts 加载JS脚本
基本用法 :
主线程 :
worker构造函数, 参数为脚本文件, 必须来自网络
postMessage() 向worker发消息
onmessage 指定监听函数, 接受子线程发回来的消息
terminate() 关闭
worker线程 :
postMessage() 向主线程发消息
onmessage 指定监听函数, 接受主线程发来的消息
close() 关闭自身
错误处理 : 主线程可以监听worker是否发生错误
注意 :
同源限制 分配的脚本文件, 必须与主线程脚本文件同源
DOM限制 worker线程所在的全局对象, 无法读取主线程所在网页的DOM对象, 可以使用navigator
对象和location
对象
全局对象限制 全局对象WorkerGlobalScope, 不同于网页全局对象Window, 很多接口拿不到
通信联系 worker线程和主线程不在同一个上下文, 不能直接通信, 必须通过消息完成
脚本限制 worker线程不能执行alert, confirm方法
文件限制 worker线程无法读取本地文件, 所加载的脚本, 必须来自网络
本文地址:https://blog.csdn.net/WP081600/article/details/111319297
下一篇: cdn模式下vue的基本用法