总结javascript基础概念(一):作用域、编译执…
2018-06-24 01:30:51来源:未知 阅读 ()
总结javascript基础概念系列计划分为三个部分:作用域,事件循环,原型链。
主要问题:
1、javaScript代码的编译和执行过程,词法作用域规则?
2、this的动态绑定方式有几种?
3、全局和函数之外是不是还有其他的作用域?
4、为什么代码规范多禁止with、eval?
一、js编译 执行
(一)、(预)编译期
JS的执行过程分为两个阶段:编译期(预处理)与执行期。报错可以据此分为两类,编译期错误和运行期错误:
SyntaxError是解析代码时发生的语法错误\
ReferenceError是引用一个不存在的变量时发生的错误。
RangeError是当一个值超出有效范围时发生的错误。
TypeError是变量或参数不是预期类型时发生的错误。
JavaScript引擎,不是逐条解释执行javaScript代码,而是按照代码块一段段编译解释执行。
1、代码块
JavaScript中的代码块是指由<script>标签分割的代码段,这样可以提高引擎的执行效率。JS是按照代码块来进行编译和执行的,代码块间相互独立,但变量和方法共享。
step 1. 读入第一个代码块。
step 2. 做语法分析,有错则报语法错误(比如括号不匹配等),并跳转到step 5。此时的报错类型为语法错误(比如括号不匹配等)、中英文等,不影响下面代码块的编译执行
step 3. 对var变量和function定义做“预编译处理”(永远不会报错的,因为只解析正确的声明)。预编译阶段,变量声明在已存在语法树中,复制移动至变量对象中。
step 4. 执行代码段,有错则报错(比如变量未定义引用错误、变量类型错误)。
step 5. 如果还有下一个代码段,则读入下一个代码段,重复step2。
step 6. 结束。
(二)、执行过程
作用域:一套变量,数据查询的规则。
JavaScript语法采用的是词法作用域(lexcical scope),也就是说JavaScript的变量和函数作用域是在写代码定义时决定的,所以 JavaScript解释器只需要通过静态分析就能确定每个变量、函数的作用域,这种作用域也称为静态作用域(static scope)。
执行环境、变量对象、内部变量表、函数表等概念都很抽象。可以用一些代码试着解释一下执行过程。
<script> hi = 'hello'; var num = 1; function fn(a){ console.log(this.num); console.log(hi); console.log(a); console.log(arguments[0]); } var fn2 = function(){ var b = 2; console.log('fn2'); return function(){ console.log(b); } } fn(2); var fn3 = fn2(); fn3(); </script>
执行过程如下:
<script> //解释型语言,以代码块为单位进行翻译、执行 // ##step 1: 语法报错 报错类型 // debugger; //GEC = { //全局执行环境 // ##step 2: vo变量对象与ao函数内的活动对象 // ##step 2.1: 变量提升,函数声明优先,两种命名方式差别 // vo:{ // fn:{ // type:function, // ao:{ // arguments:[], // a:undefined, // this:undefined // //##step 3.1: this 指向的动态绑定 几种使用形式 // //##step 3.2: 形参与arguments间联动 // }, // scopeChain:[GEC.vo] // }, // num:undefined, // fn2:undefined, // fn3:undefined, // this:window // }, // scopeChain:[GEC.vo], // ##step 3: 作用域链,包含各级变量对象指针的链表 // callStack : [GEC] // ##step 4: 调用栈,作用控制代码执行流 //} hi = 'hello'; //顺着作用域链查找变量对象上是否已有hi,有则赋值 ,没有且在非严格模式下会声明一个最外层变量 var num = 1; //num 赋值 function fn(a){ console.log(this.num); console.log(hi); console.log(a); console.log(arguments[0]); } //创建函数并赋值 var fn2 = function(){ var b = 2; console.log('fn2'); return function(){ console.log(b); } } // GEC = { // 此时的全局执行环境 // vo:{ // fn:{ // type:function, // ao:{ // arguments:[], // a:undefined, // this:undefined // }, // scopeChain:[GEC.vo] // }, // num:1, // fn2:{ // type:function, // ao:{ // arguments:[], // b:undefined, // this:undefined // }, // scopeChain:[GEC.vo] // } // hi:'hello' // fn3:undefined, // this:window // }, // scopeChain:[GEC.vo], // callStack : [GEC] //} fn(2); // FNEC = { // vo:{ // arguments:[2], // a:2, // this:window // }, // scopeChain:[GEC.vo,FNEC.vo], // callStack : [GEC,FNEC] // } // 函数的执行环境执行结束后销毁 var fn3 = fn2(); // FN2EC = { // vo:{ // arguments:[], // b:2, // ##step 5: 匿名函数创建,调用的全局性,赋值则闭包形成 // anonymous:{ // type:function, // ao:{ // arguments:[], // this:undefined // }, // scopeChain:[GEC.vo,FN2EC.vo] // }, // this:window // }, // scopeChain:[GEC.vo,FN2EC.vo], // callStack : [GEC,FN2EC] // } // 执行后返回一个匿名函数,回到全局环境 赋值给fn3 ,FN2EC.vo留在内存中。生成闭包占用内存,易造成内存泄漏 // GEC = { //全局执行环境 // vo:{ // fn:{ // type:function, // ao:{ // arguments:[], // a:undefined, // this:undefined // }, // scopeChain:[GEC.vo] // }, // num:1, // fn2:{ // type:function, // ao:{ // arguments:[], // b:undefined, // this:undefined // }, // scopeChain:[GEC.vo] // } // hi:'hello' // fn3:{ // type:function, // ao:{ // arguments:[], // this:undefined // } // scopeChain:[GEC.vo,FN2EC.vo] // } // this:window // }, // scopeChain:[GEC.vo], // callStack : [GEC] // } // FN3EC = { // vo:{ // arguments:[], // this:window // }, // scopeChain:[GEC.vo,FN2EC.vo,FN3EC.vo], // callStack : [GEC,FN3EC] // } </script>
(三)、作用域欺骗
欺骗词法作用域:with,eval
with 会在作用域链前增加一个对象,会从对象属性中查找,修改赋值。但无法新增属性;对于查找不到的赋值会向外层查询。
eval();
可以传入执行字符串代码,就像本就在那个位置。
两个最大的问题是会影响引擎的代码优化,性能下降。
块级作用域
全局和函数作用域之外,存在另外的作用域
Catch 捕获的变量只在内部有意义
<script> // ES6代码: { let a = 2; console.log(a); }; console.log(a); // 转为ES5代码: try{ throw undefined; }catch(a){ a = 2; console.log(a); } console.log(a); </script>
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:vue项目实战总结
- javascript面向对象入门基础详细介绍 2020-03-29
- JavaScript函数表达式详解及实例 2020-03-25
- 如何用javascript连接access数据库 2020-03-20
- js中去掉字串左右空格 2020-03-20
- Javascript中的经典技巧 2020-03-20
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash