变量提升
js引擎的工作方式是先解析代码,获取所有被声明的变量,然后再一行一行运行。
这样就会造成所有变量的声明语句都会被提升到代码的头部,这个就是变量提升。
复制代码
undefined与null的区别
为什么会有null和undefined?
在javascript设计之初,只设计了null来表示“无”, null可以自动转为0, 比如:
Number(null) //0
5+null //5
但是js的设计者觉得这样还不够,因为null 一开始就像在java里面一样被当做一个对象,我们可以发现
typeof(null) //object
但是js设计者觉得,表示“无”的值最好不是一个对象,而且在那个时候,js还没有错误处理机制,如果null被自动转为0的话
会很不容易被发现
所以他又设计了一个undefined
所以区别是:
null 表示一个空对象,转为数值时是 0
undefined 表示“此处无定义”的初始值,转为数值是NaN
复制代码
falsy值
null
undefined
0
false
'',""
NaN
注意: 空数组和空对象 对应的布尔值是true
js中的数值
js中的所有数字都是以64位浮点数形式储存的,即使是整数也是如此
所以: 1 === 1.0 //true 1和1.0是相同的 是同一个数
所以js底层是没有整数的,所有数字都是小数(64位浮点数)
遇到小数计算的时候要格外小心:
0.1 + 0.2 // 0.30000000000000004
复制代码
原始类型值的改变 vs 对象值的改变
var a = 1;
var b = a;
a = 2;
b //1
以上变量只是值的拷贝,所以 a的值改变不会影响b的值
var a = {'a': 1};
var b = a;
a.a = 3;
b.a //3
以上是 a和b指向的是同一个对象,他们都是对这个对象的引用,修改其中一个变量其他的都会改变。
var a = {'a': 1}
var b = a;
a = 1;
b // {'a': 1}
以上 a的值的改变 并不会影响b ,因为b 里面存储的还是之前那个对象的地址,那个对象的值没有改变所以b不会改变
复制代码
for ..in ..循环
- 遍历的是对象所有可遍历的属性,会跳过不可遍历的属性
-
- 不仅遍历对象自身的属性,还遍历继承的属性
一般情况下 都是只想遍历自身的属性,所以在遍历的时候可以结合 hasOwnProperty来判断一下某个属性是否是变量自身的属性
var a = {
'a': 1,
'b': 2
}
for (var key in a) {
if (a.hasOwnProperty(key)) {
console.log(a)
}
}
复制代码
函数本身的作用域
函数也是一个值,也有自己的作用域,他的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关
var a = 1;
var x = function () {
console.log(a)
}
function f() {
var a = 2;
x();
}
f() // 1
因为 函数在外部声明,所以绑定的是外部的作用域,所以可以取到的a是1
复制代码
同样,函数要是在函数体内部声明,那么其绑定的作用域就是函数体内部
function foo() {
var a = 22;
function bar() {
console.log(a)
}
return bar;
}
var a = 33;
var f = foo();
f(); // 22
运行f()的时候,也就是运行 bar() ,而 bar()是在foo函数内部声明的,所以绑定的是foo内部,
所以取的a 就是foo 内部的a,所以打印出的是22而不是33
复制代码
闭包
在函数的作用域的基础上我们来理解一下闭包这个知识。
我们来看一个例子:
function f1() {
var a = 33;
}
console.log(a) // c is not defined
我们在函数b中定义了一个变量a,但是我们在函数外部去访问这个变量a的时候就会报错,提示c未定义
因为a的作用域是在f1内部,所以外部是访问不到的,
那么我们怎样可以在外部拿到这个a呢?
我们可以在函数f1中再定义一个函数,然后再把这个函数return 出去,在外部执行,
因为函数的作用域是其声明时的作用域,与运行时的作用域无关。
function f2() {
var a = 33;
function f3() {
console.log(a);
}
return f3;
}
var f = f2();
var h = f() //33
以上函数在运行f2的时候,返回的是 f3函数,然后我们再执行f3函数,此时 就可以打印出a,
因为f3 是在f2内部定义的,他的作用域就是f2内部,所以 f3是可以拿到a的值的,所以就不会报错
复制代码
闭包就是上面的函数f3,即: 可以读取其他函数内部变量的函数。