美文网首页
查缺补漏前端的小知识点

查缺补漏前端的小知识点

作者: Indomi | 来源:发表于2019-08-12 15:19 被阅读0次

查缺补漏

1. defer和async属性

defer:脚本执行时不会影响页面的构造,脚本将延迟在遇到</html>后再执行,并且先于DOMContentLoaded事件执行

async:标记的脚本并不保证按照指定的先后顺序执行,并且不让页面等待脚本下载和执行,从而异步加载页面的其他内容,会在load事件前执行,可能会在DOMContentLoaded前或后执行

2. 严格模式

use strict开启严格模式,可以在函数内部声明,指明函数在严格模式下执行

3. typeof

未声明的变量同样返回undefined

// 未声明
// var age

typeof age // undefined

4. for in

可以用来枚举对象的属性

  • 循环顺序不确定
  • 建议使用之前先确定对象是否为null或者undefined(es5前会报错)

5. with

将当前作用域设置到一个特定的对象之中

with(location) {
  var qs = search.substring(1)
  var hostName = hostname
  var url = href
}

6. 没有重载

没有像java一样的重载方法来对同样的方法名写出不同的处理

如果同一个函数名的函数被定义多次,只取最后一个定义的函数

7. 垃圾回收机制

  • 标记清除:对所有变量进行标记,再对局部变量和函数内引用的变量去除标记,最后将有标记的变量作为准备清除的变量

  • 引用计数:跟踪被引用的次数,引用次数为0时在下一次垃圾回收时清除,存在循环引用的弊端,导致计数不能为0,无法被清除

  • 管理内存:在对象不被使用时手动赋值为null

随着 IE7 的发布,其 JavaScript 引擎的垃圾收集例程改变了工作方式:触发垃圾收集的变量分配、
字面量和(或)数组元素的临界值被调整为动态修正。 IE7 中的各项临界值在初始时与 IE6 相等。如果
垃圾收集例程回收的内存分配量低于 15%,则变量、字面量和(或)数组元素的临界值就会加倍。如果
例程回收了 85%的内存分配量,则将各种临界值重置回默认值。这一看似简单的调整,极大地提升了 IE
在运行包含大量 JavaScript 的页面时的性能。

8. 数组

  • 最多包含4, 294, 967, 295项

9. 数组ES5方法

  • every()
  • filter()
  • forEach()
  • map()
  • some()
  • reduce()
  • reduceRight()
  • indexOf()
  • lastIndexOf()
  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • slice()
  • concat()
  • reverse()
  • sort()

10. Date

  • Date.now()
  • Date.UTC()
  • Date.parse()

11. Function

  • 函数声明创建的函数会进行提升,在任何地方都可以使用
  • 函数表达式创建的函数只有在解析到所在代码行后才可以正常使用
  • arguments拥有属性callee指向拥有arguments的函数

12. 基本包装类型

  • 引用类型与基本包装类型的主要区别就是对象的生存期。使用 new 操作符创建的引用类型的实例,
    在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一
    行代码的执行瞬间,然后立即被销毁。这意味着我们不能在运行时为基本类型值添加属性和方法。

13. 转型函数

  • 使用new调用的基本包装类型的构造函数,和直接调用的转型函数不一样
typeof new Number(1) // 'object'
typeof Number(1) // 'number'

14. Object.defineProperty()

  • IE8是第一个实现Object.defineProperty()的浏览器版本,但限制较多,只能在DOM对象上使用(Vue只兼容到IE9原因?)实现不够彻底
  • Object.defineProperty()
  • Object.defineProperties()
  • Object.getOwnPropertyDescriptor读取属性的描述符
const obj = { a: 1 }
const descriptor = Object.getOwnPropertyDescriptor(obj, 'a')

15. 构造函数

new 的作用

1)创建一个新对象

2)将构造函数的作用域赋给新对象(this)

3)执行构造函数中的代码

4)返回这个新对象

16. 原型模式

  • 创建了自定义的构造函数之后,其原型对象默认只会取得constructor属性,其他方法都是从Object继承而来的
  • 创建的新实例内部包含一个指针指向原型对象,叫做[[Prototype]],在FirefoxSafariChrome中实现了__proto__属性能够访问到原型对象
  • 对于实例和原型对象的关系,可以使用isPrototypeOf()来检测
function Person () {
  this.name = 'John'
}
const person = new Person()
Person.prototype.isPrototypeOf(person) // true
Object.prototype.isPrototypeOf(person) // true

// es5 新增 Object.getPrototypeOf() 返回 [[Prototype]] 的值
// 兼容性IE9+
Object.getPrototypeOf(person) == Person.prototype // true
Object.getPrototypeOf(person).name // John
  • 遍历所有可以/不可以枚举的实例属性,使用Object.getOwnPropertyNames()
  • 实例中的指针仅指向原型,而不指向构造函数,也就是说实例访问原型是直接访问原型的指针,而不是通过访问构造函数的prototype属性间接访问的
function Person () {}
const person = new Person()
Person.prototype = {
  constructor: Person,
  sayName: function() {
    console.log('name')
  }
}
person.sayName() // Error
重写原型对象

17. 原型链继承

17.1 组合继承(伪经典继承)

  • 借用构造函数来实现对实例属性的继承,以及利用原型链来继承原型对象的属性
function Parent (name) {
  this.name = name
  this.color = ['red', 'blue', 'green']
}
Parent.prototype.sayName = function () {
  console.log(this.name)
}
function Child (name, age) {
  Parent.call(this, name)
  this.age = age
}
Child.prototype = new Parent()
Child.prototype.constructor = Child
Child.prototype.sayAge = function () {
  console.log(this.age)
}

var instance1 = new Child('a', 21)
instance1.color.push('black')
console.log(instance1.color) // red,blue,green,black
instance1.sayName() // a
instance1.sayAge() // 21

var instance2 = new Child('b', 22)
console.log(instance2.color) // red,blue,green
instance2.sayName() // b
instance2.sayAge() // 22

17.2 原型式继承

function object(o) {
  function F() {}
  F.prototype = o
  return new F()
}
  • 借助原型可以基于已有的对象创建新的对象
  • 必须有一个对象可以作为另一个对象的基础
  • es5通过新增Object.create()方法规范化了原型式继承
// 兼容性IE9+
var person = {
  name: 'a'
}
var anotherPerson = Object.create(person, {
  name: {
    value: "Greg"
  }
})

17.3 寄生式继承

  • 思路类似于寄生构造函数和工厂模式,封装一个函数实现
  • 类似于构造函数模式,不能够做到函数复用,每次传入都需要生成新的函数
function createAnother(o) {
  var clone = object(o)
  clone.sayHi = function() {
    console.log('hi')
  }
  return clone
}

17.4 寄生组合式继承

  • 解决了组合式继承方法,Child的原型对象上会多出Parent的实例属性,而Child的实例又拥有相同的属性覆盖了原型对象上属性的问题
  • 通过借用构造函数来继承属性,通过原型链的混成形式来继承方法
function Parent(name) {
  this.name = name
  this.color = ['red', 'blue', 'green']
}
Praent.prototype.sayName = function() {
  console.log(this.name)
}
function Child(name, age) {
  Parent.call(this, name)
  this.age = age
}
Child.prototype = Object.create(Parent.prototype, {
  constructor: {
    value: Child,
    writable: true,
    enumerable: false,
    configurable: true
  }
})

const child = new Child()
child.sayName()

18. 创建对象(类)

三种模式

  • 工厂模式:使用最基本的方法创建,然后返回这个对象
  • 构造函数模式:使用了this关键字去定义属性和方法,缺点是不能复用,比如函数
  • 原型模式:使用prototype来定义共享的属性或者方法

19. 函数递归

  • 存在的问题:如果说函数内递归调用时,函数名称的变量值发生了改变,就会导致出错,对外界的依赖度太大
  • arguments.callee是指向正在执行函数的指针,严格模式下会报错
function factorial(num) {
  if (num <= 1) {
    return 1
  } else {
    return num * factorial(num - 1)
  }
}
// 尝试下面的情况
var anotherFactorial = factorial
factorial = null
anotherFactorial(4) // 出错
// 解决办法,使用arguments.callee
function factorial(num) {
  num <= 1 ? return 1 : return num * arguments.callee(num - 1)
}
// 严格模式下解决办法
var factorial = (function f() {
  num <= 1 ? return 1 : return num * f(num - 1)
})

20. BOM

  • 获取屏幕宽高标准的顺序
const screenW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
const screenH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
  • document.locationwindow.location 引用的是同一个对象
  • BOM的核心对象是window,在浏览器中,是ECMAScript规定的Global对象
  • 全局定义的变量会自动成为window对象的属性,但是全局变量和window上定义的属性进行删除时有一点不同
var age = 20
window.color = 'red'

// IE9以下都报错
delete window.age // return false
delete window.color // return true

21. DOM

节点

操作api:

  • appendChild
  • insertBefore
  • replaceChild
  • removeChild
  • cloneNode(不会复制添加到DOM节点中的js事件/属性)
  • normalize

常见节点

  • document.documentElement
  • document.body
<body>
  <ul>
    <li>123</li>
  </ul>
</body>
  • 如上结构打印document.body.childNodes长度为3,第1和第3个都是TextNode,为换行符,只有中间第2个是ul标签

常见属性

  • document.title
  • document.URL
  • document.referer
  • document.domain

获取Node

  • document.getElementById
  • document.getElementsByTagName
  • document.getElementsByClassName
  • document.getElementsByName
  • children属性,HTMLCollection实例
  • 返回的是HTMLCollection,有namedItem()方法,可以筛选name属性

设置属性

  • getAttribute
  • setAttribute
  • removeAttribute

理解DOM

  • DOM操作是js中开销最大的部分,因为NodeList都是动态的,所以每次访问都会进行一次查询,为了提升性能,尽量减少DOM的操作

22. DOM扩展

  • 主要增加了选择符API(Selectors API)和HTML5的扩展

Selectors API

Selectors API Level 1

  • 兼容性IE8+
  • querySelector
  • querySelectorAll
  • querySelectorAll的返回值实际上相当于匹配元素的一个快照,而不是对文档进行动态的查询

Selectors API Level 2

  • matchesSelector方法,接收css选择符,如果匹配返回true
  • 不同浏览器的实现不同,表现为不同的前缀,不建议使用
Chrome浏览器实现

元素遍历

由于IE9及之前对于换行的标签不返回文本节点,而其他浏览器会返回一个内容为换行符的文本节点,为了弥补差异

  • childElementCount: 返回子元素的个数
  • firstElementChild: 第一个子元素
  • lastElementChild: 最后一个子元素
  • previousElementSibling: 前一个同辈元素
  • nextElementSibling: 后一个同辈元素
  • 兼容IE9+

HTML5

  • getElementsByClassName是H5添加的
  • classList属性,提供了标签类名的list,是DOMTokenList的实例
  • classList.add()
  • classList.contains()
  • classList.remove()
  • classList.toggle()
  • 支持的浏览器Firefox 3.6+ 和 Chrome(遗憾脸)
  • 这些内置类型其实继承自Object
继承关系

提高无障碍性的焦点管理

  • 通过document.activeElement属性来获取当前获得焦点的元素,通常是用户的输入,或者调用了focus()方法,文档加载期间默认指向body
  • document.hasFocus()来判断是否有焦点
  • 兼容性不错

*HTMLDocument(作用不大)

  • document.readyState: loading / complete
  • 兼容模式: document.compatMode
  • head: document.head相当于bodydocument.body
  • document.charset/document.defaultCharset: 默认UTF-16

自定义属性

  • 必须添加前缀data-,通过元素的dataset来访问
<p data-status="1"></p>
<script>
  document.getElementsByTagName('p')[0].dataset.status // 1
</script>

其他

  • innerHTML只插入script标签后并不会运行,因为是一个“无作用域”的元素,如果需要使script生效必须插入一个“有作用域”的元素(空div不行)
  • insertAdjacentHTML: 插入html,在不同的位置document.insertAdjacentHTML('位置', html)
  • beforebegin: 在当前元素的前面插入一个元素作为它的previousSibling
  • afterbegin: 在当前元素里面插入一个元素作为第一个子元素
  • beforeend: 在当前元素里面插入一个元素作为最后一个子元素
  • afterend: 在当前元素的后面插入一个元素作为它的nextSibling
  • element.scrollIntoView(),滚动到元素所在位置

性能问题

  • 使用上述的API如innerHTML进行DOM操作时,如果将带有事件处理的元素或引用了js对象的元素删除时,其绑定的内容并未删除,将导致内存的占用

相关文章

  • 查缺补漏前端的小知识点

    查缺补漏 1. defer和async属性 defer:脚本执行时不会影响页面的构造,脚本将延迟在遇到 后再执行,...

  • PMP 2018-12-03

    最后1周了 要回顾知识点 查缺补漏了 闭关修炼 希望大家都能考过

  • 查缺补漏

    计算机本科研究生相关课程参加开源项目spring源码

  • 查缺补漏

    查缺补漏是学习中最通俗的方法,知道自己哪方面知识点薄弱,就针对性的去学习,假以时日的去练习,就能攻克难点,薄弱知识...

  • 查缺补漏

    一.表格常用样式 vertical-align: 垂直方向的对齐方式middle top bottom bor...

  • 查缺补漏

  • 考试还有两个多月

    距离考试还有两个多月,没有太多的话,给自己加油。查缺补漏的背,巩固练习知识点。

  • Promise 查缺补漏

    promise 中 resolve 参数为一个 promise 时 p1是一个 Promise,3 秒之后变为re...

  • JavaScript查缺补漏

    语法 每个语句以;结束,语句块用{...}。但是,JavaScript并不强制要求在每个语句的结尾加; 第一种是=...

  • 查缺补漏 如饥似渴

    为了讲好Servlet,从头到尾的看视频,完整的扫描知识点,把之前缺少的、遗漏的都补上,从未如此踏实充足。就像搭积...

网友评论

      本文标题:查缺补漏前端的小知识点

      本文链接:https://www.haomeiwen.com/subject/uwsujctx.html