一,数据类型及其判断
基本(值)类型
Number ----- 任意数值
String ----- 任意字符串
Boolean ---- true/false
undefined — undefined
null -------- null
** 对象(引用)类型**
Object ----- 任意对象
Array ------ 数组(特别的对象)
Function ----函数(特别的对象)
二,数据类型的判断
1>基本类型
1,typeof (a);返回数据类型的字符串表达
可以判断undefined/数值/字符串/布尔值/function
但是不能判断null与object, 与array(返回值都是object)
2,a instanceof Object ;判断对象的具体类型(a是不是Object的实例)
3,=== 可以判断undefined和null
//number
console.log(typeof NaN)
console.log(typeof 1)
//string
console.log(typeof 'NaN')
//underfined
console.log(typeof a) //变量未定义,underfined
//boolean
console.log(typeof false)
//object
console.log(typeof []) //这三种都是返回Object
console.log(typeof {
})
console.log(typeof null)
//注意
console.log(typeof Object) //function
console.log(typeof Array)
console.log(typeof Function)
二,for循环中的i值问题
for(var i=0;i<3;i++){
setTimeout(function(){
console.log(i)
},1000*i)
}
//输出的结果会是三个3(第0秒,第1秒,第3秒)
这里的for操作是同步,而setTime是异步,放置在队列中等同步的for循环执行完毕之后才执行,而这里i是全局变量,已经变成3了。
把var换成let就可以,let声明多个 i ,i = 0,i = 1…每个 i 只对当前的区域有效。
三,for循环的理解
var x
for (var i=0,j=0;i<6,j<10;i++,j++){
x=i+j
}
console.log(x) //18
for循环的执行顺序是:初始条件–》条件判断(有一个满足则继续执行)–》语句体–》终止条件
所以说,最后的结果是18,for循环结束后的i和j的值都是10。
四,作用域和变量提升
1,函数内部会产生局部作用域,作用域内要查找变量时,顺着作用域由内向外查找。
2,每个作用域内通过var和function定义的数据存在变量提升,提升的优先级:前变量>函数>参数>(后变量)提升,但是变量最高有个前提是,它在调用前定义好。
3,而同一优先级别时,后写的会覆盖前面写的。
关于第一点:
<script type="text/javascript">
var a=3
function fn(){
console.log(a)
var a=4 //变量提升,相当于先定义,但是未赋值
}
fn() //undefined
</script>
关于第二,三点:
function fn(bar){
var bar=3 //变量优先级最高,如果有这行,则是3,但是,它必须写在调用之前,改成var bar就不行了,就会显示函数2
console.log(bar)
var bar=3 //优先级最低,如果只有它。则是var bar提升,underfined
function bar(){
return '函数1'
}
function bar(){
return '函数2'
} //函数的优先级第二,并且两个函数优先级别一样,后写的覆盖之前的
}
fn(5) //实参的优先级第三
var foo=function(){
console.log(444)
}
function foo(){
consloe.log(2)
}
foo() //444//在调用前就定义好,因为第二个是变量,优先级更高,不是同一优先级,就不考虑覆盖的问题
foo() //虽然是变量,但是它在调用之后才定义,不考虑,后一个函数用function定义,存在变量提升,故而是它
var foo=function(){
console.log(444)
}
function foo(){
console.log(2)
}
五,关于变量提升的总结
1,前变量>函数>参数>(后变量)提升,同一个作用域下,记住这个顺序就可以了。
2,只有在后续只有后变量提升的情况,才会去考虑把var a=1,拆分成var a,后续a=1的情况。其他时候不要拆分,用第一点理解。
第一种情况:
function fn(bar){
var bar=3
console.log(bar) //这里前变量出现,直接最高优先级,打印3
var bar=5
function bar(){
return '函数1'
}
function bar(){
return '函数2'
}
console.log(bar) //前变量出现两次,它优先,于是不看函数,两个前变量优先级一样,后者覆盖前者,故打印5
var bar=function(){
return '函数3'
}
console.log(bar) //依旧是前变量出现,最后一个覆盖之前的前变量,打印函数3
}
fn(6)
第二种情况:
function fn(bar){
//var bar=3
console.log(bar) //没有前变量出现,则函数优先级最高,后面的函数覆盖前面。打印函数2
var bar=5
function bar(){
return '函数1'
}
function bar(){
return '函数2'
}
console.log(bar) //前变量出现一次,它优先,于是不看函数,两个前变量优先级一样,后者覆盖前者,故打印5
var bar=function(){
return '函数3'
}
console.log(bar) //依旧是前变量出现,最后一个覆盖之前的前变量
}
fn(6)
第三种情况:
function fn(bar){
//var bar=3
console.log(bar) //没有前变量和函数,则参数优先级最高,打印参数6
var bar=5
// function bar(){
// return '函数1'
// }
// function bar(){
// return '函数2'
// }
console.log(bar) //前变量出现一次,它优先,于是不看参数,故打印5
var bar=function(){
return '函数3'
}
console.log(bar) //依旧是前变量出现,最后一个覆盖之前的前变量
}
fn(6)
第四种情况:
function fn(){
//var bar=3
console.log(bar) //没有前变量,则函数优先级最高,打印函数1
var bar=5
function bar(){
return '函数1'
}
// function bar(){
// return '函数2'
// }
console.log(bar) //前变量出现一次,它优先,于是不看函数,故打印5
var bar=function(){
return '函数3'
}
console.log(bar) //依旧是前变量出现,最后一个覆盖之前的前变量,打印函数3
}
fn()
第五种情况:
function fn(){
//var bar=3
console.log(bar) //没有前变量和函数,也没有参数,则后变量提升,这时候才会去拆分var a,于是打印underfined
var bar=5
// function bar(){
// return '函数1'
// }
// function bar(){
// return '函数2'
// }
console.log(bar) //前变量出现一次,它优先,于是不看函数,故打印5
var bar=function(){
return '函数3'
}
console.log(bar) //依旧是前变量出现,最后一个覆盖之前的前变量,打印函数3
}
fn()
于是:
var c = 1
function c(c) {
console.log(c)
}
c(2) // 报错c is not a function,因为有前变量存在,故c是1,不是函数。
六,var const let的区别
1.var定义的变量可以修改,如果不初始化会输出undefined,不会报错。
2,const定义的变量不可以修改,而且必须初始化。是块级作用域
3,let是块级作用域,函数内部使用let定义后,对函数外部无影响。
4,let 和 const 都是块级作用域,以{ }代码块作为作用域范围,只能在代码块里面使用
不存在变量提升,只能先声明后使用,否则会报错,在代码块内,声明变量之前,该变量都是不可用的,这个在语法上,叫做暂时性死区
在同一个代码块内,不允许重复声明
const声明的是一个只读的常量,在声明时就需要赋值,如果const声明的是一个对象,对象所包含的值是可以修改的,抽象点说就是,对象所指向的地址不能改变,而变量成员是可以修改的