常见js错误总结
文章标签
JavaScript

全局对象和全局变量对象
GO 全局对象
- 是浏览器提供的一个堆栈,用于存储属性和方法。它是一个物体
VO全局变量对象
- 是我们代码创建的变量存放的地方,也就是栈内存
全局执行上下文
与var
- 使用var,您创建一个全局变量并将其存储在VO的全局变量对象中
- 基于var创建变量将在VO和GO中保存一份副本
无var
- 不使用var创建的不是变量,而是全局对象GO的属性
输出顺序
- 首先检查它是一个全局变量对象VO
- 然后检查它是一个全局对象GO
私有执行上下文
与 var
- 在私有上下文的AO变量对象中声明一个私有变量(它是当前上下文的私有变量,与其他上下文无关)
无var
- 如果浏览器发现该变量不是私有变量,则会在上级上下文(作用域链)中搜索它。如果上级上下文不存在,则继续查找,直到EC全局上下文
- 如果没有全局上下文,则为GO属性设置1
范围链和范围
范围
- 当前函数‘[[scope]]’ = 创建当前函数的上下文
范围链
- scopeChain:
- 先找到自己的上下文,如果没有自己的则顺着作用域链向上级作用域
- 作用域链形成当函数执行时
函数执行步骤
?赋值(包括初始化参数)记忆的形式
内存堆栈
- 释放:如果内存已经被使用,则手动将值释放为null(null是空对象指针,即不引用堆内存)
- 不释放:如果有变量或者其他存储堆内存地址的东西,堆内存现在被视为已占用,无法释放或销毁
内存堆栈
- 释放:当页面关闭时,全局堆内存将被销毁。正常情况下,只要函数执行完毕,生成的私有堆内存就会被销毁并释放(不包括无限递归模式和无限循环模式)
- 不释放:如果当前上下文(通常是当前上下文)的某些内容)上下文中创建的堆)被上下文之外的另一个变量或事务占用,那么当前上下文无法从堆栈中释放
内存释放机制
- 搜索参考方法(webkit内核):浏览器有自动垃圾回收机制。定期回收并释放所有未占用的内存(这种垃圾回收机制比其他语言更全面)。取消占用后会减1,如果减到零,浏览器就可以释放
var,让我们
重复这句话
- 在当前上下文中,无论使用什么方法,只要声明了这个变量,就不能基于let重复声明,会报错
- 代码中是否未检测到重复声明执行阶段,但是在词法解析阶段
- 阶段检测到的词法错误 SyntaxError 会在词法解析阶段报错,当前代码不会被执行。
- ReferenceError 语法错误会在代码执行阶段报错。将执行错误之前的代码
窗口属性
let声明的变量只是全局变量,与GO无关
var声明的变量是全局变量,这和给GO(窗口)设置属性是一样的,两者创建了映射机制
临时死区
- 根据类型检测未声明的变量不会报错,结果会是‘undefined’
- 如果后面的let语句中要使用这个变量,会根据之前的检测类型报错,并且不能被声明。之前用过
构造函数执行步骤
- 初始化作用域链
- 形式参数赋值
- 变量提升
- 首先,在当前上下文中创建一个对象(该对象是当前类的实例)-浏览器默认执行的操作Let this在当前上下文中点新创建的对象 - 浏览器默认做什么
- 执行代码
- 代码执行后,如果没有设置 return,浏览器默认返回一个新创建的对象 - 浏览器应该做什么默认
原型和链式原型
- 每个函数诞生时都带有一个属性:prototype(原型)。 prototype属性值是一个对象(浏览器默认会分配堆内存)
- 在类的prototype对象中,有一个内置属性:constructor(构造函数),属性值是当前类(函数)本身,所以类又称为构造函数
- 每个对象天生就有一个属性:_proto_(原型链),属性的值就是原型的原型。包含当前实例(对象)的类
原型链搜索机制
- 首先寻找你自己的个人特质。如果有私有属性,则调用私有属性
- 否则默认根据原型链属性__proto__,在有它的类原型的原型中查找公共属性和方法
- 如果没有,根据prototype原型中的__proto__继续向上查找,直到找到Object.prototype
寄生虫联合遗传
- 手机继承+替代原型继承
function Parent() {
this.x = 100
}
Parent.prototype.getX = function getX() {
return this.x
}
function Child() {
Parent.call(this)
this.y = 200
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
Child.prototype.getY = function getY() {
return this.y
}
let c1 = new Child
检测不同类型的数据
类型
- null类型的结果是'object'(这是浏览器的BUG,所有值在计算时都是以二进制编码存储的,浏览器将前三位000视为对象),二进制前缀为null 是三位数字 000,因此它被识别为对象,但不是对象。这些是空对象指针和基本类型值)
实例
- 只要当前类的原型出现在实例的原型链中,就会返回true。
构造函数
- 本身无法解决数据类型检测,使用实例类型检测(无法重定向)
Object.prototype.toString.call()
- 每种数据类型的构造函数原型都有一个toString方法
- 除了Object.prototype中的toString返回当前实例的类信息(用于检测数据类型),否则所有字符串都会改变。
- Object.toString,toString方法中的this是一个对象的实例,即检测数据类型,即这个是谁,检测
- Object.prototype.toString.call的数据类型(value ) 于是执行了toString方法,在调用的基础上,该方法显示出检测到的数据的值,这样就可以实现数据类型的检测了
二叉树
预购遍历
function preOrder(node){
if(!(node==null)){
divList.push(node);
preOrder(node.firstElementChild);
preOrder(node.lastElementChild);
}
}
中序遍历
function inOrder(node) {
if (!(node == null)) {
inOrder(node.firstElementChild);
divList.push(node);
inOrder(node.lastElementChild);
}
}
后序遍历
function postOrder(node) {
if (!(node == null)) {
postOrder(node.firstElementChild);
postOrder(node.lastElementChild);
divList.push(node);
}
}
检查对称二叉树
function isTreeSymmetric(t) {
if (!t){
return true
}
return isTreeEqual(t.left, t.right)
}
isTreeEqual = function(x, y) {
if (!x && !y){
return true
}
if (!x || !y){
return false
}
if (x.value === y.value){
return isTreeEqual(x.left, y.right) && isTreeEqual(x.right, y.left)
} else {
return false
}
}
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。