NOTE: 学习 JavaScript 书籍和文档的笔记;最近一年应该会很少更新,如果有需要请 fork.
- 《深入理解ES6》
- 《深入理解JavaScript系列》--汤姆大叔
- 《JavaScript高级程序设计》
- 《JavaScript设计模式与开发实践》
- 《Web性能权威指南》
- 浏览器组成和执行原理
- JavaScript知识集合
- 01-函数节流和防抖
- 02-深拷贝-浅拷贝
- Github_fe-interview_仓库笔记
- JavaScript-集锦
- Javascript掘金小册
- 重学前端-winter
- JS-原型图讲解.md
- JS-继承.md
- 浏览器的进程和线程.md
- 详解_执行栈-任务队列-事件循环.md
- JavaScript 常见基础语法
- 1.1
childNodes
和children
的区别: - 1.2 JS 中的根对象:
Object.prototype
对象 - 1.3 ES5 和 ES6 中关于 Object 上的一些方法:
- 1.4 在浏览器中获取 "当前页面的可视高度" 和 "文档的总高度" 的方法总结:
- 1.5
typeof
和instanceof
操作符的区别: - 1.6
Object.prototype.toString.call()
检测数据类型: - 1.7 关于 js 中 this 指向的讲解:
- 1.8
cloneNode()
方法 - 1.9
mouseover
和mouseenter
的区别 -- (JS高程 13.4.3节) - 1.10 JSON 对象有两个方法:
JSON.stringify()
和JSON.parse()
- 1.11 "标准的"对象和函数
- 1.12 日期格式化
- 1.13
Array.prototype
- 1.14
localStorage
对象 - 1.15 客户区坐标位置 (
clientX
和clientY
) - 1.16
Object.keys()
方法使用示例 - 1.17 ES6 新增方法
Object.assign()
- 1.18
cookie
- 1.1
- assign [ə'saɪn] --v.分配, 指定, 派, 调派
- She has been assigned to a new job. 她被派去担任新职务了.
- receiver [rɪ'siːvə] --n.接收者
- supplier [səˈplaɪə] --n.提供者
- inheritance [ɪn'hɛrɪtəns] --n.继承; 遗产.
- by inheritance. 由继承
- an inheritance of $50,000. 五万美元的遗产.
- He spent all his inheritance in a year. 他一年就花光了所获得的全部遗产.
- expire [ɪk'spaɪə] vi.到期, 期满, 断气
- expire date 过期日期
childNodes
包括元素节点和文本节点, 而 children
只包括元素节点.
Object.prototype
对象是一个空的对象, 我们在 JS 中遇到的每个对象,实际上都是从 Object.prototype
对象克隆而来的, Object.prototype
对象就是他们的原型.
- ES5 -
Object.keys()
方法取得对象上所有可枚举的实例属性. 这个方法接受一个对象作为参数, 返回一个包含所有可枚举属性的字符串数组.- 示例: 见下面的
#### 1.16 Object.keys() 方法使用示例
- 示例: 见下面的
- ES5 -
Object.getOwnPropertyNames()
: 【取得自身的属性名】. -- 《JavaScript高级程序设计》Chapter 6 - ES5 -
Object.getPrototypeOf()
方法, 返回任意指定对象的原型. 对象原型的真实值被存储在内部专用属性[[Prototype]]
中, 调用getPrototypeOf()
方法返回存储在其中的值. - ES6 -
Object.is()
: 《深入理解ES6》(P76) 弥补全等运算符的不准确运算. 比如之前 +0 等于 -0, NaN 不等于 NaN. - ES6 -
Object.assign()
分配 - ES6 -
Object.setPrototypeOf()
方法可以改变任意指定对象的原型. 接受2个参数:- (1).被改变原型的对象
- (2).替代第一个参数原型的对象.
- 示例:《深入理解ES6》\chapter04_扩展对象的功能性\chapter04-扩展对象的功能性.md
视口: 浏览器窗口中当前网页的可见区域. 它不包括浏览器的地址栏, 工具栏, 状态栏. -- 《深入解析CSS》-- 2.4
// - 确定浏览器中页面视口(viewport)大小
// - HTML5 新增.
var pageViewportWidth = window.innerWidth;
var pageViewportHeight = window.innerHeight;
// - 下面为兼容写法:(`<!DOCTYPE html>` 是这种写法,以前古老的写法除外)
if (typeof pageWidth != "number") {
pageViewportWidth = document.documentElement.clientWidth;
pageViewportHeight = document.documentElement.clientHeight;
}
// - 获取文档的高度和宽度
let docScrollHeight = Math.max(
document.documentElement.clientHeight, document.documentElement.offsetHeight,
document.documentElement.scrollHeight
);
确定一个值是哪种基本类型使用 typeof 操作符, 是哪种引用类型使用 instanceof 操作符.
typeof 123; // "number"
typeof false; // "boolean"
let o = {};
let a = [];
if (o instanceof Object) {}
if (a instanceof Array) {}
Object.prototype.toString.call(ele)
: 通过获取 Object
原型上的 toString
方法, 让方法中的 this
变为需要检测的数据类型, 并且让方法执行.
const obj = {name: "WANG"};
const str = "250";
const bool = true;
const arr = [20, 30];
console.log(Object.prototype.toString.call(obj)); // [object Object]
console.log(Object.prototype.toString.call(str)); // [object String]
console.log(Object.prototype.toString.call(bool)); // [object Boolean]
console.log(Object.prototype.toString.call(arr)); // [object Array]
《Javascript设计模式与开发实践》/第一部分--基础知识/第2章-this_call_apply/第2章--this.md
- 要分清楚 this 和 作用域 Scope 之间的区别, this 是当前对象的指向问题, Scope 是作用域(全局作用域 和 本地作用域)的问题, Scope 讲解见:
《深入理解JavaScript系列》--汤姆大叔/12-1_理解JavaScript的Scope.md
《深入理解JavaScript系列》--汤姆大叔/12-变量对象(Variable Object).html
《深入理解JavaScript系列》--汤姆大叔/13-this/13-this.html
cloneNode()
方法不会复制添加到 DOM 节点中的 JavaScript 属性, 例如事件处理程序等. 这个方法只复制特性、(在明确指定的情况下也复制)子节点, 其他一切都不会复制.
mouseenter
:在鼠标光标从元素外部首次移动到元素范围之内时触发. 这个事件不冒泡, 而且在光标移动到后代元素上不会触发.mousemove
:当鼠标指针在元素内部移动时重复地触发.
let book = {
title: 'Professional JavaScript',
authors: ['Nicholas C. Zakas'],
edition: 3,
year: 2011
}
// {"title":"Professional JavaScript","authors":["Nicholas C. Zakas"],
// "edition":3,"year":2011}
let jsonText = JSON.stringify(book);
如果在使用 JSON.parse()
转换一个字符串时在浏览器中报这个错误:
Uncaught SyntaxError(未捕获的语法错误): Unexpected token o in JSON atposition 1 (JSON 位置 1 处的令牌 o)
表明,当前数据已经是对象了, 不需要再次转换. 这个错误实际上是 [object Object]
内的 o
? 待做笔记: 深入理解JSON.stringify()
- (1.) 一个 Javascript 对象就是键和值之间的映射. 键是一个字符串(或者 Symbol), 值可以是任意类型的值. 这使得对象非常符合哈希表.
- (2.) 函数是一个附带可被调用功能的常规对象. (觉得这个解说很好)
function getTime(time) {
if (time !== "" || time !== undefined) {
var data, year, month, day, hour, minute, second;
data = new Date(time);
year = data.getFullYear();
month = data.getMonth() + 1;
// month = month < 10 ? '0' + month : month;
day = data.getDate();
// hour = data.getHours();
// minute = data.getMinutes();
// second = data.getSeconds();
return year + "-" + month + "-" + day;
}
}
- 1、将 arguments (类数组对象)转换为数组, 或者把 NodeList 对象转换为数组(比如一组li):
Array.prototype.slice.call(arguments);
- 2、取得 arguments 类数组的第一项:
Array.prototype.shift.call(arguments);
- 3、取得 arguments 类数组除去第一项剩余的项:
Array.prototype.slice.call(arguments, 1);
(传入参数 1 表示被返回的数组包含从第二个参数开始的所有参数)
// - 此兼容函数来自 JS高程, 不过 2020 年了应该已经用不到了.
function getLocalStorage() {
if (typeof localStorage == "object") {
return localStorage;
} else if (typeof globalStorage == "object") {
return globalStorage[location.host];
} else {
throw new Error("Local storage not available.");
}
}
// - 使用方法存储数据
localStorage.setItem("name", "Nicholas");
// - 使用属性存储数据
localStorage.book = "Professional JavaScript";
// - 使用方法读取数据
let name = localStorage.getItem("name");
// - 使用属性读取数据
let book = localStorage.book;
// - 移除属性
localStorage.removeItem("name");
鼠标事件都是在浏览器视口中特定位置上发生的. 这个位置信息保存在事件对象的 clientX
和 clientY
属性中. 所有浏览器都支持这两个属性, 他们的值标是事件发生时鼠标指针在视口中的水平和垂直坐标: event.clientX
, event.clientY
.
Object.keys()
方法取得对象上所有可枚举的实例属性. 这个方法接受一个对象作为参数, 返回一个包含所有可枚举属性的字符串数组.
- 示例 (1)
function Person(name, age, job) { this.name = name; this.age = age; this.job = job } Person.prototype.sayName = function () { console.log(this.name); }; let keys = Object.keys(Person.prototype); console.log("keys:", keys); // ['sayName'] // - 如果想得到所有实例属性, 无论它是否可枚举, 可以使用 // `Object.getOwnPropertyNames()` (取得自身属性名) 方法: let keys2 = Object.getOwnPropertyNames(Person.prototype); // - 注意结果包含了不可枚举的 constructor 属性 console.log("keys2:", keys2); // keys2: [ 'constructor', 'sayName' ] let p1 = new Person("Rob", 36, 'Software Engineer'); console.log(Object.keys(p1)); // [ 'name', 'age', 'job' ]
- 示例 (2)
let introduction = { name: 'W', age: 30, job: 'Software Engineer', doing: true }; // [ 'name', 'age', 'job', 'doing' ] console.log(Object.keys( introduction));
- 示例 (3)
// - 混合(Mixin) 是 js 中实现对象组合的一种模式. 在一个 mixin 方法中, 一个对象 // 接受来自另一个对象的属性和方法. 许多 js 库中都有类似的 mixin 方法: function mixin(receiver, supplier) { Object.keys(supplier).forEach(function (key) { receiver[key] = supplier[key]; }) } function EventTarget() { } EventTarget.prototype = { constructor: EventTarget, emit: function (parameter) { console.log(parameter); }, on: function () { // ... } }; const inheritance = {}; // - mixin() 函数遍历 supplier 的自有属性赋并复制到 receiver 中 // (此处的复制只是浅复制, 当属性值为对象时只复制对象的引用). 这样一来, // receiver 不通过继承就可以获得新属性. mixin(inheritance, EventTarget.prototype); // - inheritance 接受 EventTarget.prototype 对象的所有行为从而使 // inheritance 可以通过 emit() 方法发布事件或通过 on() 方法订阅事件. inheritance.emit("somethingChanged"); // somethingChanged // - ES6 新增方法: Object.assign(): // + 上面的 mixin() 调用可以直接替换为 -- ES6 的 Object.assign(). // 即使这样 Object.assign() 仍然是潜拷贝. Object.assign(inheritance, EventTarget.prototype); inheritance.emit("somethingChange again");
Object.assign()
方法可以接受任意数量的源对象, 并按指定的顺序将属性复制到接收对象中.
更详细讲解见: ./《深入理解ES6》/chapter04_扩展对象的功能性/chapter04-扩展对象的功能性.md
中的 ` ### 3. 新增方法 --> Object.assign() 方法
示例:
// - 简化了上面 1.16 的示例 (3)
function EventTarget() { }
EventTarget.prototype = {
constructor: EventTarget,
emit: function (parameter) {
console.log(parameter);
},
on: function () {
// ...
}
};
const inheritance = {};
Object.assign(inheritance, EventTarget.prototype);
inheritance.emit("somethingChange again");
详细讲解见: ./《JavaScript高级程序设计》/Chapter23-离线应用与客户端存储/chapter23-离线应用与客户端存储.md
let CookieUtil = {
// - 读取 cookie
get: function (name) {
var cookieName = encodeURIComponent(name) + "=",
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null,
cookieEnd;
if (cookieStart > -1) {
cookieEnd = document.cookie.indexOf(";", cookieStart);
if (cookieEnd == -1) {
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent(
document.cookie.substring(
cookieStart + cookieName.length,
cookieEnd
)
);
}
return cookieValue;
},
// - 写入 cookie
set: function (name, value, expires, path, domain, secure) {
var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);
if (expires instanceof Date) {
cookieText += "; expires=" + expires.toGMTString();
}
if (path) {
cookieText += "; path=" + path;
}
if (domain) {
cookieText += "; domain=" + domain;
}
if (secure) {
cookieText += "; secure";
}
document.cookie = cookieText;
},
// - 删除 cookie
unset: function (name, path, domain, secure) {
this.set(name, "", new Date(0), path, domain, secure);
}
}
// - 调用示例
// - 设置 cookie
CookieUtil.set("name", "Nicholas");
CookieUtil.set("book", "Professional JavaScript");
// - 读取 cookie 的值
alert(CookieUtil.get("name")); //"Nicholas"
alert(CookieUtil.get("book")); //"Professional JavaScript"
// - 删除 cookie
CookieUtil.unset("name");
CookieUtil.unset("book");
写一个高度为0的额外的输入框,并设置 autocomplete='new-password'
属性,就可以解决问题了.
下面的表将所有运算符按照优先级的不同从高(20)到低(1)排列。
优先级 | 运算类型 | 关联性 | 运算符 |
---|---|---|---|
21 | 圆括号 |
n/a(不相关) | ( … ) |
20 | 成员访问 |
从左到右 | … . … |
需计算的成员访问 |
从左到右 | … [ … ] |
|
new (带参数列表) |
n/a | new … ( … ) |
|
函数调用 | 从左到右 | … ( … ) |
|
可选链(Optional chaining) | 从左到右 | ?. |
|
19 | new (无参数列表) | 从右到左 | new … |
18 | 后置递增(运算符在后) | n/a |
… ++ |
后置递减(运算符在后) | … -- |
||
17 | 逻辑非 | 从右到左 | ! … |
按位非 | ~ … |
||
一元加法 | + … |
||
一元减法 | - … |
||
前置递增 | ++ … |
||
前置递减 | -- … |
||
typeof | typeof … |
||
void | void … |
||
delete | delete … |
||
await | await … |
||
16 | 幂 | 从右到左 | … ** … |
15 | 乘法 | 从左到右 |
… * … |
除法 | … / … |
||
取模 | … % … |
||
14 | 加法 | 从左到右 |
… + … |
减法 | … - … |
||
13 | 按位左移 | 从左到右 | … << … |
按位右移 | … >> … |
||
无符号右移 | … >>> … |
||
12 | 小于 | 从左到右 | … < … |
小于等于 | … <= … |
||
大于 | … > … |
||
大于等于 | … >= … |
||
in | … in … |
||
instanceof | … instanceof … |
||
11 | 等号 | 从左到右 |
… == … |
非等号 | … != … |
||
全等号 | … === … |
||
非全等号 | … !== … |
||
10 | 按位与 | 从左到右 | … & … |
9 | 按位异或 | 从左到右 | … ^ … |
8 | 按位或 | 从左到右 | … | … |
7 | 逻辑与 | 从左到右 | … && … |
6 | 逻辑或 | 从左到右 | … || … |
5 | 空值合并 | 从左到右 | … ?? … |
4 | 条件运算符 | 从右到左 | … ? … : … |
3 | 赋值 | 从右到左 | … = … |
… += … |
|||
… -= … |
|||
… **= … |
|||
… *= … |
|||
… /= … |
|||
… %= … |
|||
… <<= … |
|||
… >>= … |
|||
… >>>= … |
|||
… &= … |
|||
… ^= … |
|||
… |= … |
|||
… &&= … |
|||
… ||= … |
|||
… ??= … |
|||
2 | yield | 从右到左 | yield … |
yield* | yield* … |
||
1 | 展开运算符 | n/a | ... … |
0 | 逗号 | 从左到右 | … , … |