编程语言分类动态类型语言和静态类型语言两种。 动态类型语言是指在运行期间才去做数据类型检查的语言,也就是说,在用动态类型的语言编程时,不用给任何变量指定数据类型,该语言会在第一次赋值给变量时,在内部将数据类型记录下来。javascript就是动态类型语言的代表。
在javascript中,可以在修改变量值的同时修改值的类型
var message = 'hi'; message = 100;//有效,但不推荐
变量松散类型的特性总结起来有两点:一是声明时不用给变量指定数据类型;二是赋值时可以修改数据类型
变量作用域
变量的作用域(scope),又叫执行环境(execution context),是程序源代码中定义这个变量的区域
作用域分为全局作用域和函数作用域(又叫局部作用域)两种
全局作用域是最外围的一个执行环境,在web浏览器中,全局执行环境被认为是window对象。所有全局变量和函数都是作为window对象的属性和方法创建的。全局变量拥有全局作用域,在javascript代码中的任何地方都是有定义的。全局作用域直到应用程序退出例如关闭网页或浏览器时才会被销毁
在函数内声明的变量只在函数体内有定义。它们是局部变量,作用域是局部性的。函数参数也是局部变量,它们只在函数体内有定义。函数作用域中的所有代码执行完毕后,该作用域被销毁,保存在其中的所有变量和函数定义也随之销毁
function test(){ var message = 'hi'; } test(); alert(message);//错误
如果省略var操作符,则会创建一个全局变量
function test(){ message = 'hi'; } test(); alert(message);//'hi'
虽然省略var操作符可以定义全局变量,但并不推荐。在局部作用域中定义的全局变量很难维护,而且如果有意地忽略了var操作符,也会由于相应变量不会马上就有定义而导致不必要的混乱,给未经声明的变量赋值在严格模式下会导致抛出ReferenceError错误
在函数体内,局部变量的优先级高于同名的全局变量,如果在函数内声明的一个局部变量或者函数参数中带有的变量和全局变量重名,那么全局变量就被局部变量遮盖
var scope = 'global'; function checkscope(){ var scope = 'local'; return scope; }; checkscope();//'local'
声明提升(hoisting)
块级作用域
块级作用域是指花括号内的每一段代码都具有各自的作用域,而javascript没有块级作用域。javascript只有函数作用域:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的
这意味着,变量在声明之前甚至已经可用。javascript这个特性被非正式地称为声明提升(hoisting),javascript函数里声明的所有变量(不涉及赋值)都被提前到函数体的顶部
[注意]其实除了变量提升,函数也被提升,到函数部分会有详细介绍
var scope = 'global'; function f(){ console.log(scope);//undefined var scope = 'local'; console.log(scope);//'local' }
//变量声明提升之后,相当于下面代码 var scope = 'global'; function f(){ var scope; console.log(scope);//undefined scope = 'local'; console.log(scope);//'local' }
javascript中没有块级作用域,所以一些程序员特意将变量声明放在函数体顶部,这种源代码非常清晰地反映了真实的变量作用域
属性变量
当声明一个javascript全局变量时,实际上是定义了全局对象window的一个属性
当使用var声明一个变量时,创建的这个变量是不可配置的,也就是说这个变量无法通过delete运算符删除
var truevar = 1; console.log(truevar,window.truevar);//1 1 delete truevar;//false console.log(truevar,window.truevar);//1 1
如果没有使用严格模式并给一个未声明的变量赋值的话,javascript会自动创建一个全局变量,以这种方式创建的变量是全局对象的正常的可配置属性,并可以删除它们
window.fakevar1 = 10; console.log(fakevar1,window.fakevar1);//10 10 this.fakevar2 = 20; console.log(fakevar2,window.fakevar2); //20 20 fakevar = 30; console.log(fakevar,window.fakevar); //30 30 delete window.fakevar1;//true delete this.fakevar2;//true delete fakevar;//true console.log(fakevar1,window.fakevar1);//报错 console.log(fakevar2,window.fakevar2); //报错 console.log(fakevar,window.fakevar); //报错