js知识点整理(201810笔记)

·  阅读 70

变量提升

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 ..循环

  1. 遍历的是对象所有可遍历的属性,会跳过不可遍历的属性
    1. 不仅遍历对象自身的属性,还遍历继承的属性

一般情况下 都是只想遍历自身的属性,所以在遍历的时候可以结合 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,即: 可以读取其他函数内部变量的函数。