Event Loop事件队列和宏任务微任务

Event Loop我们知道JavaScript是一门单线程的语言,他只能一行一行的执行代码,于是我们的代码应该都是同步的,这里我们暂时忘掉所有的异步,看一下这么做会有什么问题。用户进入了我们的网页,点击了一个按钮,触发加载更多功能,此时浏览器发起ajax请求,如果我们的代码都是同步的,那么页面会在这个请求完成之前是卡主状态的,因为需要等待该代码的完成,此时用户什么都做不了,既不能滚动页面,也无法点击其他内容,如果这个请求需要60s的时间,用户肯定会觉得,这是什么狗屎页面。这显然是不行的,因为代码阻塞导致体验特别的差,解决这个问题的办法就是加入异步功能,我们将请求的回调作为异步处理,不需...

163 1 0
Event Loop事件队列和宏任务微任务

尾调用优化

什么是尾调用优化函数的调用会在内存中形成一个调用记录,被称为调用帧,调用帧会保留调用位置和内部变量等信息,一个个调用帧形成了调用栈。而尾部调用优化,意思是:如果一个函数的结尾调用了一个函数,且这个函数不需要依赖当前函数的调用帧,那么就会只保留尾部调用的这个函数调用帧,从而节省内存。es6要求引擎实现尾部调用优化(TCO),因为如果没有TCO会导致一些JavaScript算法因为害怕调用栈限制而降低了通过递归实现的效率。由于缺失TCO确实会导致一些程序无法实现,所以它变成了一个重要的语言特性而不是隐藏的实现细节。es6确保了JavaScript开发者从现在开始可以在所有符合es6+的浏览器...

276 0 0

性能测试

性能测试如果被问到如何测试某个运算的速度,绝多数JavaScript开发者都会使用类似下面的代码:var start = (new Date()).getTime(); // ईኁDate.now() //需要测试的代码 var end = (new Date()).getTime(); console.log("用时:", (end - start));相信大部分人都是这么想的吧!但是这种方案有很多错误,这里我们能知道的只有这次运算消耗了大概这么长的时间。而它是否总是以这样的速度运行,我们基本上一无所知,你不知道JavaScript引擎这个时候有没有受到什么影响...

252 0 0

生成器 Generator

简介Promise的出现,我们可以将回调进行反客为主,不在受回调调用者的限制(控制反转和信任问题),但是它并没有解决异步编程导致的代码顺序问题,有没有一种方式,可以让我们的代码虽然是异步的,但是书写顺序却是同步的,这样完全符合我们人类大脑理解方式?console.log("同步的1"); axios({ ... }).then(() => { console.log("异步的回调,如果需要等待结果处理,代码只能写在这个回调里") }); console.log("同步的2")很明显,如果我们希望"同步...

247 0 0

语法

上下文规则大括号常见的大括号使用就是对象常量定义var a = { foo: bar() };但是还有一种不是很常用的方式,就是标签{ foo: bar() }很多人以为这种写法是一种对象常量,只是没有赋值给变量,但是事实并不是这样。{ ... }在这里只是一个普通的代码块。从语法上说这段代码是完全合法的,这里涉及到JavaScript中一个不太为人知的特性:标签语句;foo是bar()的标签,这种标签一般用来配合continue 和 break 语句进行跳出处理。比如我们有一个三层的for循环,但是break和continue只能跳出一层循环,如果我们在第三层找到了需要...

411 0 0

强制类型转换

简介将值从一种类型转换为另一种类型通常被称为类型转换,这是显式的情况,而隐式的情况被称为强制类型转换。在JavaScript中通常将它们统称为强制类型转换,而显式和隐式的区分分界线其实并不明显,它很大程度上取决你是否了解这段代码是否转换了类型,如果你知道它转换了类型,那么这段代码对于你而言就是显式的,而隐式常常是那些不了解或者是比较隐晦的代码。var a = 42; var b = a + ""; // 隐式强制类型转换 var c = String(a); // 显式强制类型转换隐式转换带来的副作用其实都是相对而言的,如果你足够了解,其实它就没有副作用,只是我们在编...

216 0 0

函数

原生函数常用的原生函数有:String()Number()Boolean()Array()Object()Function()RegExp()Date()Error()Symbol()——ES6 中新加入的!实际上,它们就是内建函数。原生函数可以被当作构造函数来使用,但是你得到的就不是常量了,而是对象。var a = new String("abc"); typeof a; // 是"object",不是"String" a instanceof String; // true Object.prototype.toStr...

246 0 0

类型和值

类型JavaScript 有七种内置类型:空值(null)未定义(undefined)布尔值( boolean)数字(number)字符串(string)对象(object)符号(symbol,ES6 中新增)除对象之外,其他统称为“基本类型”。其中数组Array和函数Function都是object的子类型,像Date这些也是同理。其中需要特殊记忆的就是null了,typeof对它的处理是有问题的:typeof null === "object"; // true正确的结果应该返回字符串类型的"null",这个bug是出自历史遗留,起因是因为Ja...

215 0 0

屏蔽属性

前言对于js的原型链继承,大部分都是知道的,但是对于以下内容,很多人可能并不清楚或者理解不完整,那就是屏蔽属性。什么是屏蔽属性,其实这个功能来源于面向对象语言中的多态,表示父级定义的属性,在子级可以自己扩展,虽然属性名相同,但是功能却可以不同。由于js的继承,它不像强类型语言是完全的复制,js对于继承是通过原型链的方式,当子级没有的情况下会通过在原型链上查找。那么子级如果需要覆写某一个属性,显然它是绝对不能直接修改原型链上的内容,这回导致所有继承的子类产生问题,这显然是不合适的。于是就有了屏蔽属性,当子级去覆写一个原型上存在的属性时,其实并不会去修改原型链的属性,而是给子级自己添加一个对...

312 0 0

对象的遍历

for...in循环可以用来遍历对象的可枚举属性列表,但是如果遍历对象的值呢?以数组为例,我们最基础的方式就是for循环:var myArray = [1, 2, 3]; for (var i = 0; i < myArray.length; i++) { console.log(myArray[i]); } // 1 2 3事实上这种并不是真的遍历值,而是在遍历下标来获取到对应的值。ES5新增了一些数组的遍历方法,比如:forEach(..)、every(..) 和 some(..);每种方法都可以接受一个回调函数并将其应用到数组每个元素上,,唯一的区别就是它们对于回...

245 0 0

属性描述符

简介在 ES5 之前,JavaScript 语言本身并没有提供可以直接检测属性特性的方法,比如判断属性是否是只读。但是从 ES5 开始,所有的属性都具备了属性描述符。var myObject = { a: 2 }; Object.getOwnPropertyDescriptor(myObject, "a"); // { // value: 2, // writable: true, // enumerable: true, // configurable: true // }输出的这个对象被称为属性描述符,我们可以通过Object.definePropert...

246 0 0

this全面解析

this绑定的规则从执行上下文中我们可以知道,函数在运行时会生成函数执行上下文,在这个里面存在着this,而this绑定谁,则由规则去定义。一共有四条规则,我们按从小到大一一讲解。默认绑定规则当其它三条规则不满足时,则使用默认绑定规则,在非严格模式下,this会被指向全局对象,也就是window,但是再严格模式下,会被指向undefined。function a() { console.log(this); //window } a();function a() { "use strict"; console.log(this); //und...

354 0 0

执行上下文

什么是执行上下文JavaScript引擎在执行代码阶段时,通常是调用函数的时候,就会先做一些准备工作,这个准备工作被称为执行上下文,简称EC,或者也可以叫做执行环境。执行上下文也是有不同的,有三个类型:全局执行上下文:最基础的执行上下文,一个程序也只会存在一个全局执行上下文,全局上下文会生成一个全局对象,这个对象就是window,并且会将该上下文的中this绑定到该全局对象上。函数执行上下文:当函数被调用时都是产生一个新的上下文对象,不管函数是否是重复调用Eval函数执行上下文:执行在 eval 函数内部的代码也会有它属于自己的执行上下文而this是由上下文中提供的,我们可以将上下文理解...

347 0 0

关于this

为什么会有thisthis在JavaScript中是一个非常复制的机制,它的存在其实是为了能让我们更好的复用代码,this提供了一种更优雅的方式来隐式“传递”一个对象引用,因此可以将API设计的更加简洁且易于复用。我们举个例子:new一个构造函数,我们可以得到一个新的实例对象,这个对象会继承原型,此时,如果没有this,如何在原型方法里去访问你的新的实例对象,以及获取属性这些操作。显然是不太好做的,难道每次都把自身作为参数传递给prototype上的方法吗?显然这非常不方便,如果使用了this,this会指向这个新的实例对象,那么我们在书写代码是就会更加方便了,复用也更加简单。这个thi...

348 0 0

块作用域的代替方案

随着ES6的let和const的声明,我们终于可以创建完整,不受约束的块作用域,但是这个功能终究是新的功能,老设备怎么办呢,它不支持啊!所以我们现在都是使用新的语法,再打垫片(polyfill)去支持新旧设备。那么块级作用域怎么实现旧设备也能用呢?以这段为例:{ let a = 2; console.log(a); // 2 } console.log(a); // ReferenceError分析之前说过的,with和catch,你会发现只能通过使用catch的方式实现这个功能。try { throw 2; } catch (a) { console....

310 0 0

闭包

前言闭包是基于词法作用域在书写代码时所产生的自然结果,不需要刻意的去创建闭包,闭包的创建和使用在代码中随处可见,我们需要的是怎么去识别和根据自己的需要去使用它。什么是闭包先看一段代码:function foo() { var a = 2; function bar() { console.log(a); // 2 } bar(); } foo();当我们运行foo函数的时候,foo函数里面会运行bar函数,打印时通过作用域链往上RHS查询,在foo函数作用域中查询到了a变量,并得到它的值。我们根据之前学习的作用域知识,很快的明白了为什么...

307 0 0

提升

前言到现在为止,我们应该知道作用域是做啥的了,以及词法作用域模式中,根据代码声明的位置和方式分配作用域的相关原理,。函数作用域和块作用域的行为是一样的,可以总结为:任何声明在某个作用域内的变量,都将附属于这个作用域。但是作用域中的变量标识符和其声明的位置却有一些微妙的联系。编译a = 2; var a; console.log(a);这段代码,其实会输出2;至于为什么,我们可以从编译的角度去理解。我们知道,JavaScript在运行之前会进行一次编译,其中就有词法分析,并将词法与对应的作用域进行关联,于是会将声明先提取出去,于是乎上述的var a;会被先取走并丢入作用域中去。当代码编译完...

302 1 0

函数作用域和块作用域

前言函数作用域和块作用域,并不是高出词法作用域的一种东西,可以将其理解为词法作用域的一些单元,如果词法作用域是房子,函数作用域和块作用域就是房间。函数作用域每个函数都会为其自身创建一个新的局部环境(函数作用域),属于这个函数的全部变量(函数内声明的),都只能在该环境范围内使用,当然也包括作用域嵌套。function foo(a) { var b = 2; // 一些代码 function bar() { // ... } // 更多的代码 var c = 3; } bar(); // ReferenceError 上述代码中,ba...

342 1 0

词法作用域

什么是词法作用域在上文中我们说道作用域的概念,这套规则是用来管理引擎如何在当前作用域以及嵌套的子作用域中根据标识符名称进行变量查找。而作用域共有两种工作模型:词法作用域动态作用域词法作用域是被普遍使用的一种工作模式,也是JavaScript所使用的,而动态作用域也是有语言在使用的,比如:Bash脚本,perl。词法作用域称之为静态作用域,这个也是由他的实际原理所提现的,具体我们往下看。词法阶段在JavaScript编译时,第一个阶段就是词法分析; 简单来说,词法作用域就是定义在词法分析阶段的作用域,换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处...

300 1 0
词法作用域

作用域是什么

什么是作用域几乎是所有编程语言的最基本的功能之一,就是能够存储变量的值,并且后续能够对这个值进行访问和修改,这种能力被称之为状态。如果没有状态这个概念,程序的使用会受到很大的限制,虽然没有状态也能执行一些简单的任务。变量的引入会有几个有意思的问题:变量存储在哪里?程序如果找到它们?解决这些问题的方式就是设计一套良好的规则来存储变量,并且之后也可以很方便的找到这些变量,这套规则被称之为作用域。编译原理JavaScript在运行的时候,如何创建一个变量,如何获取一个变量的值,都是通过作用域来实现的,可以将作用域理解为一个工具,往里面存东西,从里面拿东西等一系列操作。js的完整运行有三个模块:...

330 9 0
加载中