snowyYU

dream passionately

闭包是什么

闭包的产生

我觉得是因为闭包函数的作用域链中保存着包裹函数的活动对象,正因保留着引用,导致包裹函数不会被垃圾回收

特点

  1. 闭包会引用包含函数的整个活动对象
  2. 是个函数

闭包的作用

  1. 模拟私有方法

作用域链

作用域链和闭包脱不了干系,作用域链部分可以查看javascript作用域

相关参考

暂时只是大概读了一遍,先记下来

网络分层

自上而下

  • 应用层
  • 传输层
  • 网络层
  • 链路层
  • 物理层

前四层构成TCP/IP协议族,之所以分层,我觉得可以理解为像前端的模块化,易于管理,改动。实际上设计也变得简单,各层只需考虑自己分内的事

应用层

应用层决定了向用户提供应用服务时通信的活动。

包含FTP,DNS,HTTP

传输层

传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。

包含TCP,UDP(用户数据报协议)

网络层(网络互连层)

网络层用来处理在网络上流动的数据包。数据包是网络传输的最小数据单位。该层规定了通过怎样的路径(所谓的传输路线)到达对方计算机,并把数据包传送给对方。

IP

链路层(数据链路层)(网络接口层)

用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动、NIC(Network Interface Card,网络适配器,即网卡),及光纤等物理可见部分(还包括连接器等一切传输媒介)。硬件上的范畴均在链路层的作用范围之内。

三次握手

发送端首先发送一个带 SYN 标志的数据包给对方。接收端收到后,回传一个带有 SYN/ACK 标志的数据包以示传达确认信息。最后,发送端再回传一个带 ACK 标志的数据包,代表“握手”结束。 若在握手过程中某个阶段莫名中断,TCP 协议会再次以相同的顺序发送相同的数据包。

http

职责

生成针对目标服务器的HTTP请求报文

从输入 URL 到页面加载完成的过程中都发生了什么事情?

  • 输入URL
  • 发起请求:URL解析/DNS解析
  • 网络连接:三次握手
  • 服务器响应请求:返回数据
  • 客户端接收响应:浏览器加载/渲染页面

两个引擎

浏览器两个引擎

  1. 渲染引擎

    常称为浏览器的内核,webkit,gecko,persto(opera)

  2. js引擎

两个树

遇到的一些问题和解决办法

Unchecked runtime.lastError: The message port closed before a response was received.

调试工具中报如上的错误,查阅资料得知是chrome某个插件报的错,自己一一验证,发祥是迅雷下载插件这个毒瘤,禁用可消除如上的报错

浏览器的渲染原理简介

简书,浏览器加载解析渲染

图解http

整理一些angular相关的问题,多了再整理

angular 的数据绑定采用什么机制

脏检查机制。

双向数据绑定是 AngularJS 的核心机制之一。当 view 中有任何数据变化时,会更新到 model ,当 model 中数据有变化时,view 也会同步更新,显然,这需要一个监控。

原理就是,Angular 在 scope 模型上设置了一个 监听队列,用来监听数据变化并更新 view 。每次绑定一个东西到 view 上时 AngularJS 就会往 $watch 队列里插入一条 $watch,用来检测它监视的 model 里是否有变化的东西。当浏览器接收到可以被 angular context 处理的事件时,$digest 循环就会触发,遍历所有的 $watch,最后更新 dom。

举个栗子

<button ng-click="val=val+1">increase 1</button>

click 时会产生一次更新的操作(至少触发两次 $digest 循环)

按下按钮
浏览器接收到一个事件,进入到 angular context
$digest 循环开始执行,查询每个 $watch 是否变化
由于监视 $scope.val 的 $watch 报告了变化,因此强制再执行一次 $digest 循环
新的 $digest 循环未检测到变化
浏览器拿回控制器,更新 $scope.val 新值对应的 dom
$digest 循环的上限是 10 次(超过 10次后抛出一个异常,防止无限循环)。

自己感觉吧,绑定在$scope上的变量都会被监听,有变化时会刷新整个$scope上的队列。

相关链接

  1. 官网FAQ
  2. 知乎-如何衡量一个人的angular水平

相关概念

  1. 执行环境(execution context,有时也叫“环境”,“执行上下文”,“”,“”)
  2. 变量对象(variable object)
  3. 活动对象(activation object)

执行环境和作用域

执行环境很重要,执行环境定义了变量或函数有权访问的其他数据(难道指的就是初始化的作用域链?),决定论它们各自的行为。每个执行环境都有一个与之关联的 变量对象(包含了环境中定义的所有变量和函数)(难道执行环境只包含了一个标识符指针列表?),虽然我们的代码无法访问这个对象,但解析器在数据处理时会在后台使用它

全局执行环境是最外围的执行环境,在Web浏览器中,全局执行环节被认为是window对象

每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。

也就是说这个栈一直存在,和全局执行环境一样关闭网页时才被销毁

当代码在一个环境中执行时,会创建变量对象的一个 作用域链(scope chain)。作用域链的用途,是保证对执行环境有权访问的所有变量和函数有序的访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象,活动对象在开始时只包含一个变量,即arguments对象(这个对象在全局环境中是不存在的)。作用域链中的下一个变量对象来自包含(外部)环境,而再下个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。

作用域链存放在哪

以上大部分来自js高程这本书,下面开始图解

图解过程

step1

//myScript.js 
"use strict"    
var a=1;
var b=2; 

如图,开始时,创建全局执行环境并被推入执行环境栈
p1

step2

//myScript.js 
"use strict"    
var a=1;
var b=2; 
function foo(){
    var c=3;
    var d=4;
    console.log(c+d);
}

执行至function foo(){}也就是函数创建时,food的标识符(identifier)被加到当前(栗子中是全局变量对象)中,并且这个标识符引用了一个函数对象,函数对象中不仅包含了函数的源代码等还有[[scope]],[[Scope]]属性中保存了一条用来初始化作用域链,其指向就是当前的变量对象(全局变量对象)

注意此时并没创建函数相应的执行环境
p2

step3

//myScript.js 
"use strict"    
var a=1;
var b=2; 
function foo(){
    var c=3;
    var d=4;
    console.log(c+d);
};
foo();

执行至foo(),函数被调用,产生相应的执行环境,之后被推入执行环境栈顶,

此时产生的执行环境中的作用域链由之前函数定义时的[[scope]]而来,作用链的前端为foo的变量对象,由于这个环境是函数,创建活动对象并将其作为变量对象
p3

step4

调用foo()结束后,其执行环境会被弹出执行栈,
p4

tips

1.作用域链是本质上是一个指向变量对象的指针列表,它只是引用但不实际包含变量对象。
2.AO中包含了函数的形参、arguments对象、this对象、以及局部变量和内部函数的定义,然后AO会被推入作用域链的顶端。

感觉AO和VO里的内容差不多

EC和VO的产生过程

当函数被调用时进入EC的产生阶段

相关阅读

简书

偶尔看到的个人挺赞同的

执行环境、变量对象、活动对象和作用域链

皮卡丘的讲解

segmentfault作用域javascript1

segmentfault作用域javascript2

segmentfault作用域javascript3

讲了执行环境和变量对象的创建和执行过程,很有用

作用域

javascript中的this接触很多,但一直是模模糊糊的,在这里整理下

相关

与其他语言相比,函数的 this 关键字在JavaScript中的行为略有不同。它在严格模式和非严格模式之间也有一些区别。

读了廖雪峰老师的文章感觉文中所说的调用对象就是指执行环境,不知道可不可以这样理解

当一个函数被调用时,会创建一个 __执行环境(execution context)__及相应的作用域链,自动获取两个特殊变量:this和arguments,然后使用arguments和其他命名参数的值来初始化函数的 **活动对象(activation object)**,

(function(){}())立即执行函数

构造函数模式创建对象时,会经历以下4个步骤

  1. 创建一个新对象
  2. 见构造函数的作用域赋给新对象(因此this就指向了这个新对象)
  3. 执行构造函数中的代码(为这个对象添加属性)
  4. 返回新对象

this 指向

this总是指向调用函数的那个对象,在运行时基于函数的执行环境绑定的

纯函数调用

属于全局调用,this代表全局对象Global

function foo(){
    console.log(this);
};
foo(); //Window

作为对象方法的调用

this指向调用的函数

作为构造函数调用

this 指向当前实例对象

apply && call

apply()和call()作为函数对象的方法,可以改变函数的执行环境(调用对象)
它们的第一个参数是个对象,即作为函数内的this。

function foo(){
    console.log(this);
}
foo.call(1);  //1
foo.call('a');  //a
foo.call(true);  //true
foo.call({type:object});  //[object Object]

如上,他们的参数作为函数内的this输出

需要注意的是,传null或undefined时,将是JS执行环境的全局变量。浏览器中是window,其他环境,如node则是global。

fun.call(null);  //window or global
fun.call(undefined);  //window or global

apply()和call()唯一的区别是参数不一样,apply的第二个参数必须传入数组。

func1.call(this, arg1, arg2);
func1.apply(this, [arg1, arg2]);

适用条件

js中函数的参数不固定,当参数是明确知道数量时,用 call,而不确定的时候,用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个 __类数组__来便利所有的参数。

小小结

  1. apply() 的第一个参数是对象,第二个参数是数组,作为参数列表。

从ECMAScript规范谈this

上面说的this的指向很偏应用的,倒是像经验上的总结。具体还是要看规范的,这部分打算之后再好好写写

参考:JavaScript深入之从ECMAScript规范解读this

相关参考

call和apply

总是容易忘记 git 的一些命令和用法,在此记下我重复 google 的,哈哈,比较无序,足够多时再分类。

阅读全文 »
0%