执行上下文和执行上下文栈变化过程
1 | var scope = 'global scope' |
- 执行全局代码,创建全局执行上下文,全局上下文被压入执行上下文栈中:
1 | ECStack = [ |
ECMAScript的类型分为语言类型和规范类型。
ECMAScript的语言规范是开发者可以直接使用ECMAScript操作的,就是我们通常所说的Undefined、Null、Number、Boolean、String、Object;
而规范类型是用来用算法描述ECMAScript语言结构和ECMAScript语言类型的。规范类型包括Reference、List、Completion、Property Descriptor、Property Identifier、Lexical Environment和Environment Record。
Reference类型是用来解释诸如delete、typeof以及赋值等操作行为的。Reference是一个Specification Type,也就是“只存在于规范里的抽象类型”。它是为了更好地描述语言的底层行为逻辑才存在的,但并不存在于实际的JS代码中。
Reference由三个部分组成,分别是:
base value就是属性所在的对象或者就是EnvironmentRecord,它的值只可能是undefined、一个对象、一个布尔值、一个字符串、一个数字或者一个environment record其中一种;
referenced name就是属性的名称。
跨域资源共享标准新增了一组HTTP首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的HTTP请求方法(特别是GET以外的HTTP请求,或者搭配某些MINE类型的POST请求),浏览器必须首先使用OPTIONS方法发起一个预检请求(preflightrequest),从而获知服务器是否允许该跨域请求。服务器确认允许之后,才发起实际的HTTP请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括Cookies和HTTP相关数据)。
某些请求不会触发CORS预检请求,本文称这样的请求为“简单请求”。若请求满足所有下述条件,则该请求可视为“简单请求”:
POST
HTTP的头信息不超过以下几种字段:
客户端和服务器之间使用CORS首部字段来处理跨域权限:
1 | // 请求报文 |
请求首部字段Origin
表明该请求来源于http://foo.example
,响应中携带了响应首部字段Access-Control-Allow-Origin
。使用Origin
和Access-Control-Allow-Origin
就可以完成最简单的访问控制。
服务器返回的Access-Control-Allow-Origin: *
表明该资源可以被任意外域访问,如果服务端仅允许来自http://foo.example
的访问,该首部字段的内容如下:Access-Control-Allow-Origin: http://foo.example
。
http://www.example.com/dir/page.html
,协议是http://
,域名是www.example.com
,端口是80
。
http://www.example.com/dir2/other.html
:同源;http://example.com/dir/other.html
:不同源,域名不同;http://v2.example.com/dir/other.html
:不同源,域名不同;http://www.example.com:81/dir/other.html
:不同源,端口不同;https://www.example.com/dir/other.html
:不同源,协议不同。同源策略(Same Origin Policy)是有Netscape提出的一个著名的安全策略,所有支持JavaScript的浏览器都会使用这个策略。如果非同源,共有三种行为受到限制:
Flex是Flexible Box的缩写,意为“弹性布局”。设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。
1 | // 任何容器都可以指定为Flex布局 |
采用Flex布局的元素,称为Flex容器(flex container),简称“容器”。它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称“项目”。
容器默认存在两个轴,水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start
,结束为止叫做main end
;交叉轴的开始位置叫做cross start
,结束位置叫做cross end
。
项目默认沿主轴排列。单个项目占据的主轴空间叫做main size
,占据的交叉轴空间叫做cross size
。
将父构造函数的实例赋给子构造函数指向的原型对象,使得子构造函数指向的原型对象中有[[prototype]]指向父构造函数的原型对象。这样层层连接,构成原型链。
1 | function SuperType () { |
这样,新原型不仅有SuperType实例所具有的所有属性和方法,其内部还有一个指针,指向了SuperType的原型对象。最终结果就是:instance的[[prototype]]和SubType的prototype指向SubType的原型,SubType的原型(SuperType的实例)以及其他SuperType的实例的[[prototype]],和SuperType的prototype指向SuperType的原型。再加上最上层prototype指向没有被更改的函数(此处为SuperType),它的原型为Object的实例。最终的原型链如图所示:
虽然Object构造函数或对象字面量都可以用来创建单个对象,但这些方式有个明显缺点:使用同一个接口创建很多对象,会产生大量的重复代码。考虑到在ECMAScript中无法创建类,开发人员发明了一种函数,用函数来封装以特定接口创建对象的细节。
1 | function createPerson (name, age, job) { |
工厂模式解决了创建多个相似对象的问题,但没有解决对象识别的问题(即怎样知道一个对象的类型)。
JavaScript的可执行代码(executable code)的类型有三种:全局代码、函数代码、eval 代码。
当代码在执行过程中,遇到以上三种情况,都会生成一个执行上下文。执行上下文可以理解为当前代码的运行环境。
(每次某个函数被调用,就会有一个新的执行上下文为其创建,即使是调用自身的函数也是如此。)
生成的执行上下文会被压入执行上下文栈中,在处于栈顶的上下文执行完毕后,就会自动出栈。全局上下文在浏览器窗口关闭后出栈。
每个执行上下文都有三个重要属性:
变量对象是与执行上下文相关的数据作用域,储存了在上下文中定义的变量和函数声明。
两者的共同点是,都是从客户端缓存读取资源;区别是,强缓存不会发送请求,协商缓存会发送请求。
Expires和Cache-Control的作用差不多,区别是,Expires是http1.0的产物,Cache-Control是http1.1的产物。两者同时存在时,Cache-Control的优先级高于Expires,而在某些不支持http1.1的环境下,Expires就会发挥作用。因此,Expires是过时的,它只是一种兼容性的写法。
Expires和Cache-Control的另一个区别是,Expires是一个具体的服务器时间,这就导致,如果服务器和客户端的时间相差过大,缓存命中与否就不是开发者所期望的。而Cache-Control是一个时间段,就更加容易控制。