JS面向对象之作用域
作用域
词法作用域
作用域
域表示的就是范围,即作用范围
- 就是一个名字在什么地方能使用,在什么地方不能使用
块级作用域
块级别的作用范围
// 在 c , java 等编程语言中,下面的语法报错
{
var num = 123; // 应该用int , 这里是伪代码
{
console.log(num); // 123
}
console.log(num); // 报错
}
在 js 中采取词法作用域
词法(代码)作用域,就是代码在编写过程中体现出来的作用范围,代码一旦写好,不用执行,他的作用范围就已经确定好了,这个就是所谓的词法作用域
在 js 中的词法作用域规则
1. 函数允许方位函数外的数据
2. 整个代码结构中只有函数可以限定作用域
3. 作用规则首先是提升规则分析
4. 就近原则如果当前作用规则有了名字,就不考虑外面的名字
在 js 中作用域分析方法
1. 先进行预解析,分析预解析过程
* 程序在执行过程, 会先将代码读取到内存中检查. 会将所有的声明在此时进行标记. 所谓的标记就是
让 js 解释器知道有这个名字, 后面在使用名字的时候, 不会出现未定义的错误. 这个标记过程就是提升.
* 声明
1. 名字的声明, 标识符的声明( 变量名声明 )
* 名字的声明就是让我们的解释器知道有这个名字
* 名字没有任何数据与之对应
2. 函数的声明
* 函数声明包含两部分
* 函数声明与函数表达式有区别, 函数声明是单独写在一个结构中, 不存在任何语句, 逻辑判断等结构中
* 首先函数声明告诉解释器有这个名字存在. 该阶段与名字声明一样
* 告诉解释器, 这个名字对应的函数体是什么**(函数名和函数体绑定链接)**
2. 再进行代码执行过程
常见的简单作用域问题
例子 1:
var num = 123;
function foo(){
console.log(num);
}
foo(); // 输出 123
分析
- 预解析
变量num变量名提升
函数foo函数名提升
- 代码执行
num赋值123,函数内区域为独立区域,可以使用外部数据,但是现在变量名相同,覆盖外面的值
函数foo执行
函数区域中变量num变量名提升
输出num 为undefined
num赋值456
输出num 为456
例子 2:
if(false){
var num = 123;
}
console.log(num); // 输出undefined
分析
- 预解析
变量名num提升
- 执行代码
if判断为false,不进入
输出num,num定义未赋值,为undefined
例子 3:
var num = 123;
function foo(){
var num = 456;
function fn(){
console.log(num); // 输出456
};
fn();
}
foo();
分析
- 预解析
变量名num和函数名foo声明提升,函数名foo和函数体链接
- 执行代码
num = 123, 赋值
执行函数, 函数内部声明提升,变量名num和函数名fn
变量num=456, 执行函数fn
输出num, fn函数内部没有num,向上级寻找
num=456, 输出num
例子 4:
var num = 123;
function foo1(){
var num = 456;
function foo2(){
num = 789;
function foo3(){
console.log(num); // 输出789
}
foo3();
}
foo2();
}
foo1(); // 输出456
console.log(num); // 输出123
分析
- 预解析
变量名num和函数名foo1声明提升,函数名foo1和函数体绑定
- 执行代码
num = 123, 赋值
执行函数foo1, 变量名num和函数名foo2声明提升, 函数名foo2和函数体绑定
num = 456, 赋值
执行函数foo2, num在foo2函数中没有, 访问上级foo1得到num, num = 789, 赋值函数名foo3声明提升并且绑定函数体
执行函数foo3, 输出num, foo3中没有num,访问上级,得到num = 789
输出num为789
跳出函数, 输出num为123
例子 5:
if ( ! 'a' in window ) {
var a = 123;
}
console.log( a ); // undefined
分析
- 预解析
变量a声明提升
- 执行代码
判断window中是否存在a,a存在
判断为false,不执行if中的代码
输出a,为undefined
复杂的作用域问题
例子 1
if ( true ) {
function f1 () {
console.log( 'true' );
}
} else {
function f1 () {
console.log( 'false' );
}
}
f1();
分析
新版浏览器
- 预解析
无,函数f1被浏览器认为是函数表达式,不进行变量名提升
- 执行代码
if判断进入true
执行函数表达式f1
输出结果为true
旧版浏览器
- 预解析
函数f1变量声明提升,f1函数名和最后一个函数体连接在一起
- 执行代码
if判断进入true
执行f1
输出false
例子 2
if ( false ) {
function f1 () {
console.log( 'true' );
}
} else {
function f1 () {
console.log( 'false' );
}
}
f1();
分析
新版浏览器
- 预解析
无,f1为函数表达式,没有进行声明提升
- 执行代码
if判断
执行f1
输出false
旧版浏览器
- 预解析
函数名f1,声明提升,函数名和最后一个函数体链接在一起
- 执行代码
if判断
执行f1
输出false
例子 3
var num = 123;
function f1() {
console.log( num );
}
function f2() {
var num = 456;
f1();
}
f2();
分析
- 预解析
声明提升,变量num,函数名f1,f2,函数名和函数体链接
- 执行代码
num = 123
执行函数f2
变量num赋值456
执行函数f1
输出num,函数里面没有,向上寻找,上级为(0级作用域链),num=123,输出num为123
例子 4
var num = 123;
function f1() {
console.log( num );
}
function f2() {
num = 456;
f1(num);
}
f2();
分析
- 预解析
变量名num,函数名f1,f2声明提升,函数名和函数体链接一起
- 代码执行
num=123
执行函数f2
num=456,f2中没有num,向上级寻找得到num为123,将num = 123赋值,num = 456
执行f1, f1中没有num, 向上级寻找得到num为456
输出num,num=456,输出num456
JS面向对象之作用域的更多相关文章
- 带你一分钟理解闭包--js面向对象编程
上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...
- JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...
- 原生JS面向对象思想封装轮播图组件
原生JS面向对象思想封装轮播图组件 在前端页面开发过程中,页面中的轮播图特效很常见,因此我就想封装一个自己的原生JS的轮播图组件.有了这个需求就开始着手准备了,代码当然是以简洁为目标,轮播图的各个功能 ...
- js面向对象+一般方法的选项卡
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Js面向对象编程
Js面向对象编程 1. 什么是面向对象编程? 我也不说不清楚什么是面向对象,反正就那么回事吧. 编程有时候是一件很快乐的事,写一些小游戏,用编程的方式玩游戏等等 2. Js如何定义一个 ...
- 拖拽系列二、利用JS面向对象OOP思想实现拖拽封装
接着上一篇拖拽系列一.JavaScript实现简单的拖拽效果这一篇博客将接着对上一节实现代码利用JS面向对象(OOP)思维对上一节代码进行封装; 使其模块化.避免全局函数污染.方便后期维护和调用:写到 ...
- JS面向对象笔记二
菜单导航,<JS面向对象笔记一>, 参考书籍:阮一峰之<JavaScript标准参考教程> 一.构造函数和new命令 二.this关键字 三.构造函数和new命令 四.构造函 ...
- 【JavaScript】 JS面向对象的模式与实践 (重点整治原型这个熊孩子 (/= _ =)/~┴┴ )
参考书籍 <JavaScript高级语言程序设计>—— Nicholas C.Zakas <你不知道的JavaScript> —— KYLE SIMPSON 在JS的面向 ...
- javascript(面向对象,作用域,闭包,设计模式等)
javascript(面向对象,作用域,闭包,设计模式等) 1. 常用js类定义的方法有哪些? 参考答案:主要有构造函数原型和对象创建两种方法.原型法是通用老方法,对象创建是ES5推荐使用的方法.目前 ...
随机推荐
- CMOS与BIOS
BIOS与CMOS的区别 : 1. 所谓BIOS,实际上就是微机的基本输入输出系统(Basic Input-Output System),其内容集成在微机主板上的一个ROM芯片上,主要保存着有关微机系 ...
- 打砖块(codevs 1257)
题目描述 Description 在一个凹槽中放置了n层砖块,最上面的一层有n块砖,第二层有n-1块,……最下面一层仅有一块砖.第i层的砖块从左至右编号为1,2,……i,第i层的第j块砖有一个价值a[ ...
- POJ1182 食物链---(经典种类并查集)
题目链接:http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submission ...
- mysqli_insert_id
mysqli_insert_id($mysqli),这个函数一开始我用的时候老是返回0,疯掉了,百度了n次,问了n个人,搞了几天,就是解决不了,最后我把他换成面对对象编程,终于成功了,开心,也许这就是 ...
- Docker原理 -- namespace与CGroup
命名空间 PID(Process ID) 进程隔离 NET(Network) 管理网络隔离 IPC(InterProcess Communication) 管理跨进程通信的访问 MNT(Mount) ...
- 【洛谷 P4168】[Violet]蒲公英(分块)
题目链接 题目大意:给定\(n\)个数和\(m\)个求区间众数的询问,强制在线 这题我\(debug\)了整整一个下午啊..-_- 从14:30~16:45终于\(debug\)出来了,\(debug ...
- [bzoj3224]Tyvj 1728 普通平衡树——splay模板
题目 你需要写一种数据结构支援以下操作. 插入元素. 删除元素. 查询元素的排名. 查询第k小的元素. 查询元素前趋. 查询元素后继. 题解 BBST裸题. 代码 #include <cstdi ...
- Mark : Bootstrap fileInput控制预览页面上传、删除、详情按钮
Bootstrap fileInput默认预览上传效果: 而我们可能想要的结果是: 这时候可以通过初始参数layoutTemplates来控制:
- C#字节数组的常用解码处理方法
在某些情况下,比如说串口通信或者读取二进制的文件,通常会得到一个byte数组形式的数据. 然而对于这个数据处理常常令人苦恼,因为通常通信情况下,并不是一个字节代表一个字符或者某个数据,而是数据夹杂在字 ...
- DELPHI用const来提高应用程序在多核多线程下的性能
来自:http://bbs.csdn.net/topics/330048800 --------------------------------------------------------- 我们 ...