变量对象
基本数据类型
五种:number/string/boolean/null/unfinished
基本数据类型没有原型,也没有构造函数
保存在栈中,大小固定
实用typeof检测类型
· typeof null:返回的是object
undefined实际上代表了不存在的值(non-existence of a value)。
· 任何声明变量时没有提供一个初始值,都会有一个为undefined的默认值
· 当试图访问一个不存在的对象属性或数组项时,返回一个undefined值
· 如果省略了函数的返回语句,返回undefined
· 函数调用时未提供的值(没有接受到实参的形参)结果将为undefined参数值
· undefined是一个预定义的全局变量(不像null关键字)初始化为undefined值
null通常用作一个空引用一个空对象的预期,就像一个占位符
· 通过分配null值,有效地清除引用,并假设对象没有引用其他代码,指定垃圾收集,确保回收内存。
引用类型
Strine/Number/Boolean/Date/Array/Math/Object/Function
值是对象.保存在堆中
引用类型的变量实际上是一个指针,指向堆内存中的对象
赋值的时候复制的是指针地址
用instanceof检测类型
检测一个对象的类型,强烈推荐使用 Object.prototype.toString 方法
Object.prototype.toString.call([]) // "[object Array]"Object.prototype.toString.call({}) // "[object Object]"Object.prototype.toString.call(2) // "[object Number]"console.log(Object.prototype.toString.call(null)); // "[object Null]"console.log(Object.prototype.toString.call(undefined));// "[object Undefined]"
函数
函数声明必须带有标示符(Identifier)(就是大家常说的函数名称),而函数表达式则可以省略这个标示符
函数声明只能出现在程序或函数体内
不能出现在Block(块)({ ... })中,例如不能出现在 if、while 或 for 语句中。因为 Block(块) 中只能包含Statement语句, 而不能包含函数声明这样的源元素
如果function foo(){}被包含在一个函数体内,或者位于程序的最顶部的话,那它就是一个函数声明。
function foo(){} // 声明,因为它是程序的一部分
(function(){ function bar(){} // 声明,因为它是函数体的一部分 })();
函数的声明方式会得到提升,且如果有相同的函数,会覆盖
var bar = function foo(){}; // 表达式,因为它是赋值表达式的一部分new function bar(){}; // 表达式,因为它是new表达式(function foo(){}); // 函数表达式:包含在分组操作符内
函数声明会在任何表达式被解析和求值之前先被解析和求值,即使你的声明在代码的最后一行,它也会在同作用域内第一个表达式之前被解析/求值
函数声明在条件语句内虽然可以用,但是没有被标准化,也就是说不同的环境可能有不同的执行结果,所以这样情况下,最好使用函数表达式
如果我们的代码中返回多个闭包的情况,如果没有手动设置null的话,内存不会被自动释放。
立即执行函数
在一个表达式后面加上括号(),该表达式会立即执行
错误的写法:function (){ /* code */ }(); //期望是立即调用一个匿名函数表达式,结果是进行了函数声明,函数声明必须要有标识符做为函数名称。
下面2个括弧()都会立即执行
· (function () { /* code */ } ()); // 推荐使用这个
· (function () { /* code */ })(); // 但是这个也是可以用的
闭包
JS变量作用域
· 全局变量和局部变量。Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。另一方面,在函数外部自然无法读取函数内的局部变量
· 父对象的所有变量,对子对象都是可见的,反之则不成立
作用
· 通过闭包,可以在函数外面访问到内部的变量
· 让这些变量的值始终保持在内存中。
闭包就是将函数内部和函数外部连接起来的一座桥梁。
从外部读取局部变量:就是在函数的内部,再定义一个函数
闭包就是能够读取其他函数内部变量的函数。
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。
函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是Javascript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!
括号 ()是一个分组操作符
直接打印函数名(不带括号),是打印函数整体代码
直接打印函数名(带括号),是打印函数的返回值
function f1(){ var n=999; function f2(){ alert(n); // 999 }return f2; }
8