天天看点

javascript对象排序_回顾JavaScript

javascript对象排序_回顾JavaScript
  • JavaScript的特点与特性
JavaScript是一种解释型的脚本语言,C、C++等语言先编译后执行,而JavaScript是在程序的运行过程中逐行进行解释。

在javascript变量中可以存放两种类型的值:原始值和引用值。

原始值存储在栈上的简单字段,也就是值直接存储在变量所标示的位置内。

引用值存储在堆内的对象,栈内变量保存的是指向堆内对象的指针值。

在javascript中有5种基本类型:Undefined,Null,Boolean,Number,String。

引用类型其实就是对象,类似其他语言中类实例的概念。

var b = true; // 存储在栈上
var num = 20; //存储在栈上
var b = new Boolen(true); //存储在堆内
var num = new Number(20); // 存储在堆内
           
  • 堆(heap)与栈(stack)

heap是没有结构的,数据可以任意存放。heap用于复杂数据类型(引用类型)分配空间,例如数组对象、object对象。

stack是有结构的,每个区块按照一定次序存放(后进先出),stack中主要存放一些基本类型的变量和对象的引用,存在栈中的数据大小与生存期必须是确定的。可以明确知道每个区块的大小,因此,stack的寻址速度要快于heap。

程序运行时,每个线程分配一个stack,每个进程分配一个heap,也就是说,stack是线程独占的,heap是线程共用的。此外,stack创建的时候,大小是确定的,数据超过这个大小,就发生stack overflow错误,而heap的大小是不确定的,需要的话可以不断增加。所以这里只看stack的大小限制。

在javascript中,函数就是对象, this引用的是调用当前函数的函数上下文。

可以通过call()和apply()方法来显式的指定函数上下文。Call的第一个参数被用来作为调用函数的上下文,其他参数作为被调用函数的参数传入被调用函数。Apply()和Call()差不多,只不过第二个参数是数组。

  • 闭包

要理解闭包,首先必须理解Javascript特殊的变量作用域。

变量的作用域无非就是两种:全局变量和局部变量。

Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。

函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!

闭包的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

闭包​developer.mozilla.org

javascript对象排序_回顾JavaScript

由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

  • js是单线程

总所周知,JavaScript 是以单线程的方式运行的。

进程和线程都是操作系统的概念。进程是应用程序的执行实例,每一个进程都是由私有的虚拟地址空间、代码、数据和其它系统资源所组成;进程在运行过程中能够申请创建和使用系统资源(如独立的内存区域等),这些资源也会随着进程的终止而被销毁。而线程则是进程内的一个独立执行单元,在不同的线程之间是可以共享进程资源的,所以在多线程的情况下,需要特别注意对临界资源的访问控制。在系统创建进程之后就开始启动执行进程的主线程,而进程的生命周期和这个主线程的生命周期一致,主线程的退出也就意味着进程的终止和销毁。主线程是由系统进程所创建的,同时用户也可以自主创建其它线程,这一系列的线程都会并发地运行于同一个进程中。
function foo() {
    console.log( 'first' );
    setTimeout( ( function(){ console.log( 'second' ); } ), 5);
 
}
 
for (var i = 0; i < 1000000; i++) {
    foo();//先输出 first 随后都是 second
}
           

因为setTimeout 是异步的,浏览器是

事件驱动的(Event driven)

,浏览器中很多行为是

异步(Asynchronized)

的,会创建事件并放入执行队列中。javascript引擎是单线程处理它的任务队列,你可以理解成就是普通函数和回调函数构成的队列。当异步事件发生时,如mouse click, a timer firing, or an XMLHttpRequest completing(鼠标点击事件发生、定时器触发事件发生、XMLHttpRequest完成回调触发等),将他们放入执行队列,等待当前代码执行完成。

执行完循环,才会执行setTimeout的内容

  • js栈、任务队列
javascript对象排序_回顾JavaScript

实例图

(1)所有同步任务都在主线程上执行,形成一个 执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

(4)主线程不断重复上面的第三步。

Js 中,有两类任务队列:宏任务队列(macro tasks)和微任务队列(micro tasks)。宏任务队列可以有多个,微任务队列只有一个。那么什么任务,会分到哪个队列呢?

宏任务:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering.

微任务:process.nextTick, Promise, Object.observer, MutationObserver.

  • js解释器

1.词法分析器

2.句法解析器

3.字节码生成器

4.字节码解释器

  • JavaScript中容易踩的坑

JavaScript 都有什么坑?​www.zhihu.com

javascript对象排序_回顾JavaScript
  • var 与 let

如下:

b() // call b
console.log(a) // undefined  a不会报错,因为下文有定义,但是又是在定义之前调用

var a = 'Hello world'

function b() {
    console.log('call b')
}
           

b是函数,同样在定义之前使用,但是函数提升是优先于变量提升的

b() // call b second

function b() {
    console.log('call b fist')
}
function b() {
    console.log('call b second')
}
var b = 'Hello world'
           

ES6中引入了

let,let

不能在声明前使用,防止出现var的错误

  • 作用域问题
function b() {
    console.log(value)
}

function a() {
    var value = 2
    b()
}

var value = 1
a()//输出1
           

可以考虑下 b 函数中输出什么。你是否会认为 b 函数是在 a 函数中调用的,相应的 b 函数中没有声明

value

那么应该去 a 函数中寻找。其实答案应该是 1。

当在产生执行环境的第一阶段时,会生成

[[Scope]]

属性,这个属性是一个指针,对应的有一个作用域链表,JS 会通过这个链表来寻找变量直到全局环境。这个指针指向的上一个节点就是该函数声明的位置,因为 b 是在全局环境中声明的,所以

value

的声明会在全局环境下寻找。如果 b 是在 a 中声明的,那么 log 出来的值就是 2 了。

function a() {
    var value = 2
    function b() {
    	console.log(value)
	}
	b()
}
var value = 1
a()//输出2
           
  • JavaScript的语法词法特性

JS 共有 6 个原始值,分别为

Boolean, Null, Undefined, Number, String, Symbol

,这些类型都是值不可变的。

有一个易错的点是:虽然

typeof null

是 object 类型,但是 Null 不是对象,这是 JS 语言的一个很久远的 Bug 了。

对于对象来说,直接将一个对象赋值给另外一个对象就是浅拷贝,两个对象指向同一个地址,其中任何一个对象改变,另一个对象也会被改变。记得曾经对两个数组进行排序,由于两个数组拷贝的同一个数据,导致数组的排序相互影响

var a = [1, 2]
var b = a
b.push(3)
console.log(a, b) // -> 都是 [1, 2, 3]
           
//TODO
  • 其他

参考:

闭包​developer.mozilla.org

javascript对象排序_回顾JavaScript

学习Javascript闭包(Closure) - 阮一峰的网络日志​www.ruanyifeng.com 人类身份验证 - SegmentFault​segmentfault.com JavaScript 标准参考教程(alpha)​javascript.ruanyifeng.com JavaScript运行原理解析 · JS重塑学习 · 看云​www.kancloud.cn

继续阅读