JavaScript--变量作用域、函数作用域及作用域链
2017-05-05 14:33
309 查看
JavaScript–变量作用域、函数作用域及作用域链
变量作用域
一个变量的作用域是代码中定义这个变量的区域。全局变量拥有全局作用域,在js代码中任何地方都有定义
在函数内声明的变量只在函数体内有定义——局部变量,函数参数也是局部变量,只在函数体内有定义
在函数体内,局部变量的优先级高于同名的全局变量。
var scopr="global";//全局变量 function checkscope(){ var scope="local";//同名局部变量 return scope;//返回局部变量值而不是全局变量 } checkscope();//local
函数作用域
JS没有类似C语言的块级作用域,使用函数作用域:变量在声明他们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。function test(o){ var i=0;//i在整个函数体内有定义 if(typeof o=="object"){ var j=0;//j在函数体内是有定义的,不仅仅是这个代码段内 for(var k=0;k<10;k++){ //k在函数体内是有定义的,不仅仅是这个循环内 console.log(k);//输出0-9 } console.log(k);//输出10 } console.log(j);//j已经定义了,但可能没有初始化 }
由于函数作用域的特点,js实现了声明提前:函数里声明的所有变量(但不涉及赋值),都提前至函数顶部。
如下例:
var scope="global"; function f(){ console.log(scope);//输出undefined,而不是global var scope="local";//变量在这里初始化赋值。但变量本身在函数体内任何地方都有定义 console.log(scope);//输出local }
相当于:
var scope="global"; function f(){ var scope; console.log(scope);//输出undefined,而不是global scope="local";//变量在这里初始化赋值。但变量本身在函数体内任何地方都有定义 console.log(scope);//输出local }
声明函数和变量
声明变量,变量不能删除(delete),属性可以删除变量的声明只有一种方式,那就是用var关键字声明,直接赋值不是一种声明方式。这仅仅是在全局对象上创建了新的属性(而不是变量)。
var a=10;//变量 b=10;//不是变量,是在全局对象上创建了新的属性(不会声明提前) alert(delete b); // true alert(window.b); // undefined
但是,在“eval”的上下文中,变量是可以删除的:
eval('var a = 10;'); alert(window.a); // 10 alert(delete a); // true alert(window.a); // undefined
函数声明
函数的声明有三种方式
(1)function name( ){ }直接创建方式 (2)new Funtion构建函数创建 (3)给变量赋值匿名函数方法创建 function add(a,b){ return a+b; } var add=new Function("a", "b", "return a+b;"); var add = function(a,b){ return a+b; } add(4,5);
当变量名和函数名声明时相同,函数优先声明。
作用域链
将局部变量看作是自定义实现的对象的属性每一段JS代码(全局代码或函数)都有一个与之关联的作用域链(scope chain)
这个作用域链是一个对象列表或者链表,这组对象定义了这段代码“作用域中”的变量。当JS查找变量X的值的时候,它从链中的第一个对象开始查找,如果这个对象有名为x的属性,则直接使用该属性值,否则JS继续查找下一个对象,直至找完不存在X,抛出引用错误一场(ReferenceError)
在JS的最顶层代码中,作用域链就是一个全局对象组成
function add(a,b){ var sum = a + b; return sum; } 此时作用域链(Scope Chain)只有一级,就为Global Object scope(add) -> Global Object(VO)
当调用这个函数的时候,它创建了一个新的对象来存储它的局部变量,将这个对象添加至保存的那个作用域链上。
add(1,2); //此时作用域链就有2级了 scope(add) -> activation object(AO)-> Global Object(VO)
嵌套的函数体内,作用域链至少有3个对象
function add(a,b){ var sum = a + b; function add2() { var z = 30; console.log(a + b + z); }; add2() } add(3,4); //此时scope -> add2.AO -> add.AO -> Global Object
此时这三个对象:
add2.AO = { z : 30, __parent__ : add.AO } add.AO = { this:window, arguments : [3,4], a : 3, b : 4, add2 : <reference to function>, __parent__ : <Global Object> } Global Object = { this:window, add: <reference to function>, __parent__ : null }
相关文章推荐
- JavaScript 变量作用域、函数作用域、作用域链
- Javascript的变量作用域居然可以跨越多个函数!
- JavaScript中的作用域与函数和变量声明的提升
- 轻松搞定--作用域,变量、函数提升,作用域链
- 通过函数作用域和块级作用域看javascript的作用域链
- JavaScript学习记录day6-函数变量作用域、解构赋值与方法
- [JavaScript] 模拟块级作用域、私有变量/函数
- javascript基础:函数传递参数的方式、参数数组、变量范围(变量作用域)
- JavaScript_事件、函数、变量作用域
- JavaScript 函数总体概述(函数声明/参数传递/返回值/加载/变量和作用域/变量声明提升/匿名函数/回调函数)
- 从函数作用域和块级作用域看javascript的作用域链
- JavaScript-4.2函数,变量作用域---ShinePans
- javascript 函数初探 (三)--- javascript 变量的作用域
- javascript中的回调函数中变量作用域
- JavaScript的函数作用域与作用域链详解
- JavaScript高级之---词法作用域的含义、变量的作用域链
- Javascript的变量作用域居然可以跨越多个函数!
- javascript和python函数中变量作用域的区别
- JavaScript学习记录day6-函数变量作用域、解构赋值与方法
- JavaScript的变量及函数(变量提升、嵌套作用域、条件语句、严格模式、IIFE、闭包、模块化、this、原型)