以语言的角度学习 Js 的底层原理(与 DOM 无关):① 作用域链 ② 词法分析 ③ 闭包 ④ 面向对象(原型链)

① 作用域链

例1

<script>
var c = 5;
function t1(){
var d = 6;
function t2(){
var e = 7;
alert(c + d + e);
}
t2();
}
t1();
</script>

弹出:18

首先在函数内寻找变量,如果寻找不到,则往外层寻找,直到全局(window)区域

例2

<script>
var c = 5;
function t1(){
var d = 6;
function t2(){
var e = 7;
var d = 3;
alert(c + d + e);
}
t2();
}
t1();
</script>

弹出:15

寻找变量的顺序是由内向外,变量 d 首先找到了 3 ,从而不会继续向外曾寻找变量 d 。

例3

<script>
alert(window.d);
alert(window.e); function t(){
d = 5;
var e = 6;
}
t(); alert(window.d);
alert(window.e);
</script>

依次弹出:undefined,undefined,5,undefined

d 没有加 var ,仅仅是一个赋值操作,寻找 t 域内的函数,没找到,继续寻找 → window,widow.d = 5(第 3 个 alert)

var 是在函数运行的上下文中,声明一个变量,如果不加 var,则是赋值操作,但不要狭隘地理解为 声明了一个全局变量(见例4)。

例4

<script>
function t1(){
var d;
function t2(){
d = 5;
e = 6;
}
t2();
}
t1();
console.log(d);
console.log(e);
</script>

console 中打印出:Uncaught ReferenceError: d is not defined

如果只

 console.log(e); 

则打印出 6

t2 内部没有 d 变量,仅仅是赋值操作,往外层寻找 d 变量,在t1 函数中找到了,于是把变量 d 的值赋给了 5;

e 也仅仅是赋值操作,并没有相应的变量,因此往外找变量,直到找到最外层(window),还是没有找到,只有 window.e = 6

如果

console.log(window.d);
console.log(e);

则打印出:

undefined
6

注意区别:以 window.*** 引用全局变量时,如果寻找不到,则作为某个属性不存在而返回 undefined;若直接以 *** 引用某变量,寻找不到则是报 *** is undefined 错误。

例5(极容易出错又极基础的面试题)

 <script>
var str1 = 'global';
function t1(){
console.log(str1);
console.log(str2);
str2 = 'local';
}
t1();
</script>

打印出:

global
Uncaught ReferenceError: str2 is not defined

【分析】:

第 4 行在执行时,在 t1 内寻找 str1,没有,于是在 window 上寻找 str1,找到,因此打印'global'

第 5 行在执行时,在 t1 内寻找 str2,没有,于是在 window 上寻找 str2,没有,因此报 str2 is undefined 错误

第 6 行(由于第 5 行出错,实际上执行不到这里),才把全局的 str2 赋值(window.str2 = 'local')

例6(例5 基础上修改:str2 前加 var)

<script>
var str1 = 'global';
function t1(){
console.log(str1);
console.log(str2);
var str2 = 'local';
}
t1();
</script>

打印出:

global
undefined

加了 var ,则声明了一个变量。

【分析】:

js 代码自上而下执行,但是js 代码的整体运行分:① 词法分析 和 ② 运行期,

在自上而下执行之前,先有词法分析过程

在该例中

第 1 步:分析t1 函数:

t1{

  var str2  //分析出 t1 内有 str2 局部变量。此时只是分析有改变量,并没有赋值(未执行),因此 str2 的值是undefined

}

第 2 步:执行 t1 函数:

console.log(str1);    // global

console.log(str2);    // undefined

str2 = 'local';         // 此时str2 的值为 'local'

Javascript 笔记与总结(1-1)作用域的更多相关文章

  1. javascript笔记:javascript的关键所在---作用域链

    javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript技巧也是围绕作用域进行的,今天我要总结一下关于 ...

  2. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  3. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  4. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  5. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  6. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  7. 《JavaScript 闯关记》之作用域和闭包

    作用域和闭包是 JavaScript 最重要的概念之一,想要进一步学习 JavaScript,就必须理解 JavaScript 作用域和闭包的工作原理. 作用域 任何程序设计语言都有作用域的概念,简单 ...

  8. javascript 变量 命名规范 变量的作用域

    原文:javascript 变量 命名规范 变量的作用域 大家好,我是小强老师,今天讲解的是变量 变量 小时候我们学过  这个 应用题 :  X+1=2; 问  X 等于几?  答案是 1 对了,很聪 ...

  9. 从头开始学JavaScript 笔记(一)——基础中的基础

    原文:从头开始学JavaScript 笔记(一)--基础中的基础 概要:javascript的组成. 各个组成部分的作用 . 一.javascript的组成   javascript   ECMASc ...

  10. 【原】javascript笔记之Array方法forEach&map&filter&some&every&reduce&reduceRight

    做前端有多年了,看过不少技术文章,学了新的技术,但更新迭代快的大前端,庞大的知识库,很多学过就忘记了,特别在项目紧急的条件下,哪怕心中隐隐约约有学过一个方法,但会下意识的使用旧的方法去解决,多年前ES ...

随机推荐

  1. backslash and newline separated by space

    原来是因为\  后面多了一个空格 检查写的代码中将\后面的空格去掉就可以了.

  2. stsadm.exe

    Usage: stsadm.exe -o <operation> [<parameters>] stsadm.exe -help [<operation>] Ope ...

  3. 在Android中将子View的坐标转换为父View的坐标

    在Android中,我们有时候可能会将子View的坐标转换为父View中的坐标.感觉很有用,分享给大家. 在Launcher中有这么一段代码可以完成这项工作.  public float getDes ...

  4. PhpStorm Git 配置

    首先需要安装windows下的Git版本,网上有很多我下载的是msysgit反正都差不多,不会的自己百度. 其次打开PhpStorm,点击File ,Settings ,找到Version Contr ...

  5. hrbustoj 1073:病毒(并查集,入门题)

    病毒Time Limit: 1000 MS Memory Limit: 65536 KTotal Submit: 719(185 users) Total Accepted: 247(163 user ...

  6. php截取指定字符串之间的字符串的类

    一个php截取指定字符串之间的字符串的类 <?php   class get_c_str {   var $str;   var $start_str;   var $end_str;   va ...

  7. android.intent.action.MAIN 与 android.intent.category.LAUNCHER 的验证理解 (转)

    原文地址:android.intent.action.MAIN 与 android.intent.category.LAUNCHER 的验证理解 作者: 第一种情况:有MAIN,无LAUNCHER,程 ...

  8. 小甲鱼PE详解之基址重定位详解(PE详解10)

    今天有一个朋友发短消息问我说“老师,为什么PE的格式要讲的这么这么细,这可不是一般的系哦”.其实之所以将PE结构放在解密系列继基础篇之后讲并且尽可能细致的讲,不是因为小甲鱼没事找事做,主要原因是因为P ...

  9. 小甲鱼PE详解之区块描述、对齐值以及RVA详解(PE详解06)

    各种区块的描述: 很多朋友喜欢听小甲鱼的PE详解,因为他们觉得课堂上老师讲解的都是略略带过,绕得大家云里雾里~刚好小甲鱼文采也没课堂上的教授讲的那么好,只能以比较通俗的话语来给大家描述~ 通常,区块中 ...

  10. hud1166 敌兵布阵

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...