JSON.stringify

  1. JSON.stringify(value[, replacer [, space]])

第二个参数:可以是一个函数或者一个数组

  • 为函数时:(key, value) => value,返回的是value值
  • 为数组时:只保留数组的值代表将被序列化成 JSON 字符串的属性名

第三个参数:控制结果字符串的间距

document.execCommand

  1. bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
  2. aCommandName:命令名称
  3. aShowDefaultUI:展示用户界面,Mozilla 没有实现,设置为false即可
  4. aValueArgument:一些命令的额外参数,默认为null

允许命令操作可编辑区域的元素
dom元素设置contentEditable属性为true

window.getSelection

  1. let s = window.getSelection()
  2. s.getRangeAt(0)
  3. // s.toString() 获取到选择的文字
  4. // 等价于 s + ''

document.createRange

返回一个Range对象

  1. var range = document.createRange();
  2. range.setStart(startNode, startOffset);
  3. range.setEnd(endNode, endOffset);

eg. https://www.jianshu.com/p/ad2f818cc3b0

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>range</title>
  8. </head>
  9. <body>
  10. <p id="p">
  11. <b>Use the buttons below</b> to select or deselect the contents of this
  12. paragraph.
  13. </p>
  14. <p>
  15. 2. Use the buttons below to select or deselect the contents of this
  16. paragraph.
  17. </p>
  18. <p>
  19. 3. Use the buttons below to select or deselect the contents of this
  20. paragraph.
  21. </p>
  22. <p>
  23. 4. Use the buttons below to select or deselect the contents of this
  24. paragraph.
  25. </p>
  26. <div id="d">5. Use the buttons below to select or deselect the contents of this paragraph.</div>
  27. <button id="select-button">Select paragraph</button>
  28. <button id="deselect-button">Deselect paragraph</button>
  29. <button id="set-start-button">Set Start</button>
  30. <button id="set-end-button">Set End</button>
  31. <button onclick="deleteChar()">删除文字</button>
  32. <script>
  33. const p = document.getElementById("p");
  34. const selectButton = document.getElementById("select-button");
  35. const deselectButton = document.getElementById("deselect-button");
  36. const setStartBtn = document.getElementById("set-start-button");
  37. const setEndBtn = document.getElementById("set-end-button");
  38. selectButton.addEventListener("click", (e) => {
  39. // Clear any current selection
  40. const selection = window.getSelection();
  41. selection.removeAllRanges();
  42. // Select paragraph
  43. const range = document.createRange();
  44. range.selectNodeContents(p);
  45. selection.addRange(range);
  46. });
  47. deselectButton.addEventListener("click", (e) => {
  48. const selection = window.getSelection();
  49. selection.removeAllRanges();
  50. });
  51. setStartBtn.addEventListener("click", (e) => {
  52. var range = document.createRange();
  53. var startNode = document.getElementsByTagName("p").item(2);
  54. var startOffset = 0;
  55. range.setStart(startNode, startOffset);
  56. var endNode = document.getElementsByTagName("p").item(3);
  57. var endOffset = endNode.childNodes.length;
  58. range.setEnd(endNode, endOffset);
  59. const selection = window.getSelection();
  60. selection.removeAllRanges();
  61. selection.addRange(range);
  62. });
  63. setEndBtn.addEventListener("click", (e) => {
  64. var range = document.createRange();
  65. var endNode = document.getElementsByTagName("p").item(3);
  66. var endOffset = endNode.childNodes.length;
  67. range.setEnd(endNode, endOffset);
  68. });
  69. function deleteChar() {
  70. var div = document.getElementById("d");
  71. var textNode = div.firstChild;
  72. var range = document.createRange();
  73. range.setStart(textNode, 1);
  74. range.setEnd(textNode, 4);
  75. range.deleteContents();
  76. }
  77. </script>
  78. </body>
  79. </html>
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>1212</title>
  6. <script type="application/javascript">
  7. function delrow() {
  8. var table = document.getElementById("mytable");
  9. if (table.rows.length > 0) {
  10. var row = table.rows[0];
  11. var rangeObj = document.createRange();
  12. rangeObj.setStartBefore(row);
  13. rangeObj.setEndAfter(row);
  14. rangeObj.deleteContents();
  15. }
  16. }
  17. </script>
  18. </head>
  19. <body>
  20. <table id="mytable" border="1">
  21. <tr>
  22. <td>内容1</td>
  23. <td>内容2</td>
  24. </tr>
  25. <tr>
  26. <td>内容3</td>
  27. <td>内容4</td>
  28. </tr>
  29. </table>
  30. <button onclick="delrow()">删除第一行</button>
  31. </body>
  32. </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

bind,call,apply

可以传递我们想要的this关键词引用的对象
bind方法返回函数的拷贝值,但带有绑定的上下文,它不会立即执行
call方法会立即执行
apply方法也会立即执行
call和apply传参方式不同,call是传值,apply是传数组

reduce

  1. arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

initialValue:第一次调用callback函数的第一个参数的值。如果没有提供,则将使用数组的第一个元素。在没有初始值的空数组上调用reduce将报错

GC:垃圾回收

浏览器帮我们释放内存
evaltrycatchwith不会被回收
eval会欺骗词法作用域
with会创建新的作用域

js事件循环和消息队列

  • promise优先于setTimeout宏任务
  • promise一旦被定义,就会立即执行
  • Promiserejectresolve是异步执行,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

浏览器渲染页面过程

碎片知识点 - 图1

  • 解析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是返回对象上所有可枚举的键

箭头函数

箭头函数返回的是一个对象时,必须在圆括号之间编写

  1. getUser = (user) => ({ name: user.name, age: user.age })
  2. getList = ([x, ...y]) => [x, y]
  3. // 这种情况下,会报错SyntaxError
  4. getUser1 = (user) => { name: user.name, age: user.age }

事件传播的三个阶段

捕获阶段 => 目标 => 冒泡
捕获阶段事件通过父元素向下传递到目标元素,开始冒泡
默认情况下,事件处理程序在冒泡阶段执行

所有对象都有原型 - 错误

除基础对象外的所有对象都有原型
基础对象是指原型链终点的对象,**null**
typeof null ==> “object”

++a和a++

a++:先返回,再加
++a:先加,在返回

  1. let number = 0;
  2. console.log(number++);
  3. console.log(++number);
  4. console.log(number);
  5. // 0 2 2

模板字符串

如果使用模板字符串,则第一个参数的值始终是字符串值的数组,其余参数获取传递到模板字符串中的表达式的值

  1. function getPersonInfo(one, two, three) {
  2. console.log(one);
  3. console.log(two);
  4. console.log(three);
  5. }
  6. const person = "Lydia";
  7. const age = 21;
  8. getPersonInfo`${person} is ${age} years old`;
  9. // ["", "is", "years old"] Lydia 21

eval

eval会为字符串传递的代码求值

所有对象的键都会被储存为字符串,set除外

注意原型链底层函数中对this的操作会覆盖上层的值

continue

  1. for (let i = 1; i < 5; i++) {
  2. if (i === 3) continue;
  3. console.log(i);
  4. }
  5. // 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对象

值/对象

普通参数是值的传递,复制对象复制的是对象的引用,所以改变
对参数进行值传递时,会创建一份该值的复制

  1. function getInfo(member, year) {
  2. member.name = 'b'
  3. year = '1998'
  4. }
  5. const person = {name: 'a'}
  6. const birthDay = '1997'
  7. getInfo(person, birthDay)
  8. console.log(person, birthDay)
  9. // { name: 'b' } '1997'

Object.definedProperty

此方法添加得属性,默认为不可枚举的
Object.keys返回对象中可枚举的属性
writableenumerableconfigurable

import/export

import命令是编译阶段执行的,在代码运行之前。所以被导入的模块先运行,导入模块的文件后运行
commonjs中require和import的区别:require后,可以在运行代码时根据需要加载依赖项。

  1. // index.js
  2. console.log("running index.js");
  3. import { sum } from "./sum.js";
  4. console.log(sum(1, 2));
  5. // sum.js
  6. console.log("running sum.js");
  7. export const sum = (a, b) => a + b;
  8. // running sum.js running index.js 3
  9. // 用require加载 打印:running index.js running sum.js 3

Object.assign

拷贝源对象自身可枚举的属性到目标对象。
如果源值是一个对象引用,只会复制其引用值。

  1. let obj1 = {a: 0, b: {c: 0}}
  2. let obj2 = Object.assign({}, obj1)
  3. obj1.a = 1
  4. console.log(obj2)
  5. obj2.a = 2
  6. console.log(obj1)
  7. obj1.b.c = 1
  8. console.log(obj2)
  9. obj2.b.c = 2
  10. console.log(obj1)

队列

表的前端删除,表的后端插入操作
先进先出

Object.create

创建新对象,原型指向 oldArrayPrototype,再扩展新的方法不会影响原型

  1. // 重新定义数组原型
  2. const oldArrayPrototype = Array.prototype
  3. // 创建新对象,原型指向 oldArrayPrototype,再扩展新的方法不会影响原型
  4. const arrProto = Object.create(oldArrayPrototype)
  5. arrProto.push = function(){
  6. console.log(100)
  7. }
  8. 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( <自定义属性名> [, <默认值 ]? )

  1. .box {
  2. --1: #369;
  3. }
  4. body {
  5. background-color: var(--1, #cd0000);
  6. }
  7. // 背景为#cd0000

CSS变量不合法的缺省特性

  1. body {
  2. --color: 20px;
  3. background-color: #369;
  4. background-color: var(--color, #cd0000);
  5. }
  6. ==> 转化为
  7. body {
  8. --color: 20px;
  9. background-color: #369;
  10. background-color: transparent;
  11. }

Reflect作用

  • 与Proxy能力一一对应
  • 规范化,标准化,函数式 ```javascript const obj = {a: 1, b: 2} // ‘a’ in obj // Reflect.has(obj, ‘a’)

// delete obj.a // Reflect.deleteProperty(obj, ‘a’)

  1. - 代替Object的工具函数
  2. ```javascript
  3. const obj = {a: 1, b: 2}
  4. // Object.getOwnPropertyNames(obj)
  5. // Reflect.ownKeys(obj)

类class

  • 继承
  • 封装
    • 实例出来的对象 访问 protected 和 private 的属性,是会报错的 (在typescript中)
  • 多态

    • 父类定义方法,子类去覆盖
    • 面向接口编程

      1. class jQuery {
      2. constructor(selector) {
      3. let slice = Array.prototype.slice
      4. let dom = slice.call(document.querySelectorAll(selector))
      5. let len = dom ? dom.length : 0
      6. for (let i = 0; i < len; i++) {
      7. this[i] = dom[i]
      8. }
      9. this.length = len
      10. this.selector = selector || ''
      11. }
      12. append(node) {
      13. }
      14. addClass(name) {
      15. }
      16. html(data) {
      17. }
      18. // 此处省略若干 API
      19. }
      20. window.$ = function (selector) {
      21. return new jQuery(selector)
      22. }

UML类图

点击查看【processon】

delete操作符

delete操作符删除的是对象上的属性

AMD,CMD

AMD

  • 依赖前置
  • 提前执行
  • 用户体验好,没有延迟,依赖模块提前执行了

CMD

  • 依赖就近
  • 延迟执行
  • 性能好,用户需要时才执行

函数参数传递

函数的参数是按值传递的
把函数外部的值复制给函数内部的参数,就是把一个值复制到另一个变量一样
而引用类型是按引用传递,也就是传入函数的是原始值的地址,因此在函数内部修改参数,将会影响到原始值。

对象的拷贝

https://www.html.cn/archives/8319

页面禁用缓存

可以在 css 和 js文件链接上加入版本号

按位索引简写

  1. if(arr.indexOf(item) > -1) {} ====================================> if(~arr.indexOf(item)) {}
  2. if(arr.indexOf(item) === -1) {} ====================================> if(!~arr.indexOf(item)) {}

:::danger )运算符将返回除-1以外的任何值的真实值。** :::

Switch 简写

  1. switch (data){
  2. case 1:
  3. t1();
  4. break;
  5. case 2:
  6. t2();
  7. break;
  8. case 3:
  9. t3();
  10. break;
  11. }
  12. ======>转化为
  13. let data = {
  14. 1: t1,
  15. 2: t2,
  16. 3: t3,
  17. }
  18. data[something] && data[something]();