以语言的角度学习 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. stsadm.exe

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

  2. adbWireless 简单教程

    adbWireless:无线使用ADB(siir.es.adbWireless) 下载: http://www.coolapk.com/apk/siir.es.adbWireless >> ...

  3. hdu 4021 n数码

    好题,6666 转自:http://www.cnblogs.com/kuangbin/archive/2012/08/23/2652410.html 题意:给出一个board,上面有24个位置,其中2 ...

  4. Eclipse 导入 Hadoop 源码

    1.准备工作 jdk: eclipse: Maven: libprotoc :https://developers.google.com/protocol-buffers/ hadoop:http:/ ...

  5. 启动TOMCAT报错 java.util.zip.ZipException: invalid LOC header (bad signature)

    报错信息大致如下所示: at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect. ...

  6. http://www.111cn.net/jsp/Jsp-Servlet/45158.htm

    http://www.111cn.net/jsp/Jsp-Servlet/45158.htm

  7. Android RelativeLayout 实现左右中布局

    效果图如下: 代码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns ...

  8. Sql不区分大小写查询

    select a.* from Pair_User  a where 1=1   and   UPPER(a.UserID) like 'EMH1001%' collate Chinese_PRC_C ...

  9. bzoj1028 [JSOI2007]麻将

    1028: [JSOI2007]麻将 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1337  Solved: 601[Submit][Status][ ...

  10. BZOJ1580 : [Usaco2009 Hol]Cattle Bruisers 杀手游戏

    以贝茜为参照物,则贝茜固定于原点,每个杀手是一个圆心在某条射线上的圆. 解出每个杀手可以射杀贝茜的时间区间,然后扫描线即可,时间复杂度$O(n\log n)$. #include<cstdio& ...