- JSON.stringify
- document.execCommand
- window.getSelection
- document.createRange
- 对象的比较
- this指向
- typeof
- SPA
- null和undefined区别
- bind,call,apply
- reduce
- GC:垃圾回收
- js事件循环和消息队列
- 深浅拷贝
- DOM节点创建
- 清除浮动
- 前端网站优化
- 浏览器渲染页面过程
- 纯函数
- for…of和for…in
- args 剩余参数
- js的分号
- Symbol,Object.keys
- 箭头函数
- 事件传播的三个阶段
- 所有对象都有原型 - 错误
- ++a和a++
- 模板字符串
- eval
- 所有对象的键都会被储存为字符串,set除外
- 注意原型链底层函数中对this的操作会覆盖上层的值
- continue
- setInterval
- promise.all/promise.race
- 值/对象
- Object.definedProperty
- import/export
- Object.assign
- 队列
- Object.create
- css变量
- CSS变量不合法的缺省特性
- Reflect作用
- 类class
- UML类图
- delete操作符
- AMD,CMD
- 函数参数传递
- 对象的拷贝
- 页面禁用缓存
- 按位索引简写
- Switch 简写
JSON.stringify
JSON.stringify(value[, replacer [, space]])
第二个参数:可以是一个函数或者一个数组
- 为函数时:
(key, value) => value,返回的是value值 - 为数组时:只保留数组的值代表将被序列化成 JSON 字符串的属性名
第三个参数:控制结果字符串的间距
document.execCommand
bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)aCommandName:命令名称aShowDefaultUI:展示用户界面,Mozilla 没有实现,设置为false即可aValueArgument:一些命令的额外参数,默认为null
允许命令操作可编辑区域的元素
dom元素设置contentEditable属性为true
window.getSelection
let s = window.getSelection()s.getRangeAt(0)// s.toString() 获取到选择的文字// 等价于 s + ''
document.createRange
返回一个Range对象
var range = document.createRange();range.setStart(startNode, startOffset);range.setEnd(endNode, endOffset);
eg. https://www.jianshu.com/p/ad2f818cc3b0
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>range</title></head><body><p id="p"><b>Use the buttons below</b> to select or deselect the contents of thisparagraph.</p><p>2. Use the buttons below to select or deselect the contents of thisparagraph.</p><p>3. Use the buttons below to select or deselect the contents of thisparagraph.</p><p>4. Use the buttons below to select or deselect the contents of thisparagraph.</p><div id="d">5. Use the buttons below to select or deselect the contents of this paragraph.</div><button id="select-button">Select paragraph</button><button id="deselect-button">Deselect paragraph</button><button id="set-start-button">Set Start</button><button id="set-end-button">Set End</button><button onclick="deleteChar()">删除文字</button><script>const p = document.getElementById("p");const selectButton = document.getElementById("select-button");const deselectButton = document.getElementById("deselect-button");const setStartBtn = document.getElementById("set-start-button");const setEndBtn = document.getElementById("set-end-button");selectButton.addEventListener("click", (e) => {// Clear any current selectionconst selection = window.getSelection();selection.removeAllRanges();// Select paragraphconst range = document.createRange();range.selectNodeContents(p);selection.addRange(range);});deselectButton.addEventListener("click", (e) => {const selection = window.getSelection();selection.removeAllRanges();});setStartBtn.addEventListener("click", (e) => {var range = document.createRange();var startNode = document.getElementsByTagName("p").item(2);var startOffset = 0;range.setStart(startNode, startOffset);var endNode = document.getElementsByTagName("p").item(3);var endOffset = endNode.childNodes.length;range.setEnd(endNode, endOffset);const selection = window.getSelection();selection.removeAllRanges();selection.addRange(range);});setEndBtn.addEventListener("click", (e) => {var range = document.createRange();var endNode = document.getElementsByTagName("p").item(3);var endOffset = endNode.childNodes.length;range.setEnd(endNode, endOffset);});function deleteChar() {var div = document.getElementById("d");var textNode = div.firstChild;var range = document.createRange();range.setStart(textNode, 1);range.setEnd(textNode, 4);range.deleteContents();}</script></body></html>
<!DOCTYPE html><html><head><meta charset="utf-8" /><title>1212</title><script type="application/javascript">function delrow() {var table = document.getElementById("mytable");if (table.rows.length > 0) {var row = table.rows[0];var rangeObj = document.createRange();rangeObj.setStartBefore(row);rangeObj.setEndAfter(row);rangeObj.deleteContents();}}</script></head><body><table id="mytable" border="1"><tr><td>内容1</td><td>内容2</td></tr><tr><td>内容3</td><td>内容4</td></tr></table><button onclick="delrow()">删除第一行</button></body></html>
对象的比较
当比较两边有对象时,先调用对象的toString方法转为原始类型字符串,然后比较;当string和boolean比较时,2个都先转换为number类型比较
而数组转为原始类型时,会调用数组内部的join方法
this指向
在函数中,this的指向是函数的执行环境,this取决于其被谁调用的,而不是被谁定义的
this指向是它所在上下文(定义时的位置)的环境
typeof
typeof返回的时字符串
SPA
优点:
- 用户体验好,快,内容改变不需要加载整个页面,避免了不必要的跳转和页面加载
- 减少服务器压力
- 前后端职责分明,架构清晰,前端交互逻辑,后端数据处理
缺点:
- 初次加载耗时多,需要将js,css统一加载,部分页面按需加载
- 前进后退路由管理,不能使用浏览器的前进后退功能
- SEO难度大,所有内容在一个页面动态替换,所以SEO比较弱势
null和undefined区别
- null指空值,undefined指未定义
- null在Number(null)转换为0,undefined在Number(undefined)转换为NaN
- 在使用场景上
- null
- 作为函数的参数,该函数的参数不是对象
- null代表对象的原型链的终点
- undefined
- 变量被声明了,但是未赋值,就是undefined
- 调用函数时,未提供需要的参数,为undefined
- 对象属性没有赋值,该属性的值为undefined
- 函数没有返回值,默认返回undefined
- null
bind,call,apply
可以传递我们想要的this关键词引用的对象
bind方法返回函数的拷贝值,但带有绑定的上下文,它不会立即执行
call方法会立即执行
apply方法也会立即执行
call和apply传参方式不同,call是传值,apply是传数组
reduce
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
initialValue:第一次调用callback函数的第一个参数的值。如果没有提供,则将使用数组的第一个元素。在没有初始值的空数组上调用reduce将报错
GC:垃圾回收
浏览器帮我们释放内存eval,try,catch,with不会被回收
eval会欺骗词法作用域
with会创建新的作用域
js事件循环和消息队列
promise优先于setTimeout宏任务promise一旦被定义,就会立即执行Promise的reject和resolve是异步执行,resolve()会被放到回调队列,在主函数执行完和setTimeout之前调用await执行完会让出线程。async标记的函数返回一个Promise对象
深浅拷贝
js数据类型分为基本数据类型和引用数据类型,基本数据类型保存的是值,引用类型保存的是引用地址。浅拷贝拷贝的是内存地址,深拷贝是开辟新的内存地址
DOM节点创建
- createElement
- createTextNode
- createDocumentFragment:临时节点
节点操作:
- appendChild
- insertBefore(newNode, refNode)
- removeChild
- replaceChild
清除浮动
- 父元素增加高度撑开
- 浮动元素结尾增加空标签,设置clear: both
- 父元素设置overflow: hidden
- 父元素添加伪类:after和zoom
前端网站优化
减少资源大小:
- 压缩js,css,html文件
- 符合条件的图标转为base64
- 按需加载(UI组件库)
- SPA项目,路由按需加载(import)
- Nginx开启gzip
提高加载速度:
- 图片CDN加速
- 页面使用骨架屏,提高首页加载速度
- 设置缓存
资源加载方式:
- 图片CDN加速
减少请求次数:
加载时机优化:
- 样式表放首部,js代码放尾部
link/src增加rel属性,设置prefetch/preload可预加载资源
使用图片懒加载
- 使用JPEG 2000,JPEG XG,WepP的图片格式代替现有的jpeg和png
浏览器渲染页面过程

- 解析HTML,生成DOM树
- 解析Css,生成CSSOM树
- 将DOM树和CSSOM树关联,生成渲染树
- 布局render树(Layout/reflow),负责个元素的尺寸和位置的计算
- 绘制render树(paint),绘制页面像素信息
- 将像素发送给GPU,展示在页面上
纯函数
如果输入的参数相同,无论何时调用,都会得到相同的输出结果,就是纯函数
for…of和for…in
for…of循环,迭代可迭代对象
for…in循环,遍历一个对象自有的,继承的,可枚举的,非Symbol的属性
args 剩余参数
...args剩余参数,值是一个包含所有剩余参数的数组,并且只能作为最后一个参数
js的分号
JS引擎会在语句之后自动添加上分号(自动分号插入),一个语句可以是变量,也可以是**throw**,**return**,**break**等关键字
Symbol,Object.keys
Symbol类型是不可枚举的,但是可以使用Object.getOwnPropertySymbols()访问symbol
Object.keys是返回对象上所有可枚举的键
箭头函数
箭头函数返回的是一个对象时,必须在圆括号之间编写
getUser = (user) => ({ name: user.name, age: user.age })getList = ([x, ...y]) => [x, y]// 这种情况下,会报错SyntaxErrorgetUser1 = (user) => { name: user.name, age: user.age }
事件传播的三个阶段
捕获阶段 => 目标 => 冒泡
捕获阶段事件通过父元素向下传递到目标元素,开始冒泡
默认情况下,事件处理程序在冒泡阶段执行
所有对象都有原型 - 错误
除基础对象外的所有对象都有原型
基础对象是指原型链终点的对象,**null**typeof null ==> “object”
++a和a++
a++:先返回,再加
++a:先加,在返回
let number = 0;console.log(number++);console.log(++number);console.log(number);// 0 2 2
模板字符串
如果使用模板字符串,则第一个参数的值始终是字符串值的数组,其余参数获取传递到模板字符串中的表达式的值
function getPersonInfo(one, two, three) {console.log(one);console.log(two);console.log(three);}const person = "Lydia";const age = 21;getPersonInfo`${person} is ${age} years old`;// ["", "is", "years old"] Lydia 21
eval
eval会为字符串传递的代码求值
所有对象的键都会被储存为字符串,set除外
注意原型链底层函数中对this的操作会覆盖上层的值
continue
for (let i = 1; i < 5; i++) {if (i === 3) continue;console.log(i);}// 1 2 4
如果某个条件返回true,则continue跳过迭代
setInterval
返回值是一个唯一的**id**
promise.all/promise.race
https://juejin.cn/post/6844904077537574919#heading-26
promise.all:将多个Promise实例包装成一个新的promise实例,成功返回的是一个结果数组,失败的话返回最先被reject失败状态的值。在处理多个异步处理的时很有用
promise.race:赛跑的意思,Promise.race([p1, p2, p3])哪个结果获得的快就返回哪个的值,不管结果本身是成功状态还是失败状态
then和catch返回的也是promise对象
值/对象
普通参数是值的传递,复制对象复制的是对象的引用,所以改变
对参数进行值传递时,会创建一份该值的复制
function getInfo(member, year) {member.name = 'b'year = '1998'}const person = {name: 'a'}const birthDay = '1997'getInfo(person, birthDay)console.log(person, birthDay)// { name: 'b' } '1997'
Object.definedProperty
此方法添加得属性,默认为不可枚举的Object.keys返回对象中可枚举的属性writable,enumerable,configurable
import/export
import命令是编译阶段执行的,在代码运行之前。所以被导入的模块先运行,导入模块的文件后运行
commonjs中require和import的区别:require后,可以在运行代码时根据需要加载依赖项。
// index.jsconsole.log("running index.js");import { sum } from "./sum.js";console.log(sum(1, 2));// sum.jsconsole.log("running sum.js");export const sum = (a, b) => a + b;// running sum.js running index.js 3// 用require加载 打印:running index.js running sum.js 3
Object.assign
拷贝源对象自身可枚举的属性到目标对象。
如果源值是一个对象引用,只会复制其引用值。
let obj1 = {a: 0, b: {c: 0}}let obj2 = Object.assign({}, obj1)obj1.a = 1console.log(obj2)obj2.a = 2console.log(obj1)obj1.b.c = 1console.log(obj2)obj2.b.c = 2console.log(obj1)
队列
表的前端删除,表的后端插入操作
先进先出
Object.create
创建新对象,原型指向 oldArrayPrototype,再扩展新的方法不会影响原型
// 重新定义数组原型const oldArrayPrototype = Array.prototype// 创建新对象,原型指向 oldArrayPrototype,再扩展新的方法不会影响原型const arrProto = Object.create(oldArrayPrototype)arrProto.push = function(){console.log(100)}console.log(arrProto.__proto__.push)
css变量
https://www.zhangxinxu.com/wordpress/2016/11/css-css3-variables-var/
https://www.zhangxinxu.com/wordpress/2018/11/html-js-set-css-css3-var%e5%8f%98%e9%87%8f/
IE浏览器不支持CSS变量,试试参考这个Github项目:https://github.com/jhildenbiddle/css-vars-ponyfill
语法:var( <custom-property-name> [, <declaration-value> ]? )var( <自定义属性名> [, <默认值 ]? )
.box {--1: #369;}body {background-color: var(--1, #cd0000);}// 背景为#cd0000
CSS变量不合法的缺省特性
body {--color: 20px;background-color: #369;background-color: var(--color, #cd0000);}==> 转化为body {--color: 20px;background-color: #369;background-color: transparent;}
Reflect作用
- 与Proxy能力一一对应
- 规范化,标准化,函数式 ```javascript const obj = {a: 1, b: 2} // ‘a’ in obj // Reflect.has(obj, ‘a’)
// delete obj.a // Reflect.deleteProperty(obj, ‘a’)
- 代替Object的工具函数```javascriptconst obj = {a: 1, b: 2}// Object.getOwnPropertyNames(obj)// Reflect.ownKeys(obj)
类class
- 继承
- 封装
- 实例出来的对象 访问 protected 和 private 的属性,是会报错的 (在typescript中)
多态
- 父类定义方法,子类去覆盖
面向接口编程
class jQuery {constructor(selector) {let slice = Array.prototype.slicelet dom = slice.call(document.querySelectorAll(selector))let len = dom ? dom.length : 0for (let i = 0; i < len; i++) {this[i] = dom[i]}this.length = lenthis.selector = selector || ''}append(node) {}addClass(name) {}html(data) {}// 此处省略若干 API}window.$ = function (selector) {return new jQuery(selector)}
UML类图
delete操作符
delete操作符删除的是对象上的属性
AMD,CMD
AMD
- 依赖前置
- 提前执行
- 用户体验好,没有延迟,依赖模块提前执行了
CMD
- 依赖就近
- 延迟执行
- 性能好,用户需要时才执行
函数参数传递
函数的参数是按值传递的
把函数外部的值复制给函数内部的参数,就是把一个值复制到另一个变量一样
而引用类型是按引用传递,也就是传入函数的是原始值的地址,因此在函数内部修改参数,将会影响到原始值。
对象的拷贝
https://www.html.cn/archives/8319
页面禁用缓存
可以在 css 和 js文件链接上加入版本号
按位索引简写
if(arr.indexOf(item) > -1) {} ====================================> if(~arr.indexOf(item)) {}if(arr.indexOf(item) === -1) {} ====================================> if(!~arr.indexOf(item)) {}
:::danger 〜)运算符将返回除-1以外的任何值的真实值。** :::
Switch 简写
switch (data){case 1:t1();break;case 2:t2();break;case 3:t3();break;}======>转化为let data = {1: t1,2: t2,3: t3,}data[something] && data[something]();
