泷涯生活

Code is like life. 代码 ≈ 生活

JavaScript面向对象

函数除了拿来调用外,还可以创建新的类型:

function People(name) {
	this.name = name;
	this.getName = function() {
		return this.name;
	}
}

var p = new People("Jack");
console.log(p instanceof People); // => true
console.log(p.getName()); // => "Jack"

那么,这个对象里都有什么呢?我们可以把它打印出来看看:

1

可以看到,除了我们放进去的name、getName,还有一个__proto__。它是什么,我先卖个关子。我们先看看“instanceof”,和其他语言类似:

var p = new People("Jack");
		console.log(p instanceof People); // => true
		console.log(p instanceof Object); // => true
		

我们可以笼统地认为,People继承于Object。不过,JS中的instanceof其实没有那么简单,MDN上是这样写的:The instanceof operator tests whether the prototype prototype of a constructor appears anywhere in the prototype chain of an object.

接下来我们先看看prototype是什么,将上面的People打印一下:

2

它其实就是一个普普通通的对象,那么,它和new出来的对象有什么关系?可以用这张图表示:

3

这张图是什么意思呢?在内存中,prototype和它实例化出的__proto__是同一个对象。这有什么意义?我们知道,JavaScript中会这样寻找属性、方法:

所以,我们可以这样写:

function People(name) {
	this.name = name;
}
People.prototype.getName = function() {
	return this.name;
}

var p = new People("Jack");
console.log(p.getName());
var p2 = new People("Jason");
console.log(p2.getName());

再举个例子,我们从文档中可以查到hasOwnprototype的方法,MDN上有这样的描述:

所有继承了 Object 的对象都会继承到 hasOwnprototype 方法。这个方法可以用来检测一个对象是否含有特定的自身属性;

如果我们运行p.hasOwnprototype("name"),JavaScript怎么找到hasOwnprototype的呢?它会:

操作系统、进程、线程、协程的一些事

操作系统是多久诞生的?从定义上来说,最早的时候,人们是通过各种按钮控制计算机的,这时候还没有操作系统。不过,如果我们认为,只要是让人们操作计算机的工具,都可以称为操作系统的话,说计算机从诞生之日起便有操作系统,这种话其实基本上也是正确的。操作系统的功能、原理是一直在发展的。几十年前的操作系统,和几十年后的,虽然它们都被称为操作系统,但是可能已经是两个东西了。

最早的计算机编程是通过纸带进行的。“程序员”将记载着程序的纸带放进计算机,计算机执行完毕后把结果纸带“吐”出来,这便是最早的人机交互。最早的时候计算机是独占的,你需要使用的话,就必须等前一个人用完。为了提高资源使用率,陆陆续续出现了批处理操作系统、分时操作系统和实时操作系统。分时操作系统在一定程度上已经接近于今天的操作系统了。它使用时间片的方式轮流分配CPU资源,用来处理多个用户的作业。

今天的操作系统,最基础的其实也是时间片,但是在它的基础上进行了很多改进。

计算机逐渐发展,操作系统逐渐变得复杂。操作系统有一大功能叫“资源管理”,它怎么给程序分配资源呢?于是,进程的概念也被提出来了。进程是进行资源分配和调度的基本单位。我们仅从最简单的理论上来说,进程包括两个部分,一个是Process Control Block(PCB,程序控制块)和程序块。PCB是系统用来控制一个进程的“工具”,也是进程存在的标志。PCB中包含了进程的一些基本信息,例如,进程的ID,程序运行的堆栈,程序的运行数据等。而程序块则是进程真正执行的代码。

操作系统一般通过时间片算法来管理一个进程。它把CPU分成很多个很小的“片段”,并把它们轮流分配给进程使用。当时间片耗尽后,进程就会被系统“暂停”,将它的数据放入PCB,然后进程就进入了“就绪”队列。因此,从微观角度来讲,单个CPU某一时刻只能执行一个进程。

当进程需要其他外部资源时会怎样呢?例如一个进程需要读写文件,如果缓冲区没有它需要的数据,那么就意味着内核需要去外部储存读取。外部储存的读写对计算机来说是很慢的,CPU资源不应该被白白浪费,于是,内核就会让进程进入阻塞状态。当进程需要的资源准备好的时候,进程就可以继续了吗?答案是否定的,它需要重新“排队”,才能继续运行。

线程的提出,是因为人们觉得进程切换开销太大,因此想要一个更“轻”的进程。线程提出之初,其实用处并不大,直到出现了多核心处理器。

前面提到了,进程是进行资源分配和调度的基本单位,那么,我们现在可以说,线程是进行资源调度的最小单位。与进程类似,线程也有一个叫做“Thread Control Block”的存在(TCB,线程控制块)。不过,这里需要注意,因为线程拥有的系统数据非常少,因此我们基本上忽略不计。所以说,线程并不能拥有资源,它只能使用进程的资源。线程比起进程更加轻量、灵活。进程的切换涉及到系统资源,而线程则不然。

因为以上特点,我们可以看出:

在开始介绍线程的时候,我们说到了“多核处理器”。那么,为什么多核处理器能够让线程的能力得以体现?我们先说一下基本概念:处理器(CPU)=运算器+寄存器+控制器。其中,运算器就是我们所说的“核”。多个核心共享寄存器。和进程、线程类比一下是不是很相似?进程独占资源,线程则共享资源。因此,每有一个核心,就可以有一个线程在它上面运行。

Intel前几年有一项新技术叫做“超线程”,它大概意思就是,把一个核心“伪装”成多个核心,达到同时运行多个线程的目的。众所周知,线程在运行的时候总还是会有一些浪费资源的情况,因此,“超线程”对于多线程任务会有比较明显的提升,但是对于单线程任务可能反而会有一些下降。

Copyright © 2016 - 2019 泷涯生活. 蜀ICP备14012003号-2