(文中一些小的注释可能会令大家觉得没有必要,但是对于一些童鞋可能确实有用<比如我这样的小菜鸡>小声bb)
众所周知,JavaScript变量声明共有三种关键字 var let const
对于var,在 ECMAScript 的所有版本中均可使用,而let与const只能在ECMAScript6(ES6)及之后的版本中使用。然而ES6新增的let与const直接受到了大多数程序猿的追捧即大多数童鞋不再使用var而只使用const,下面就让小王和大家好好掰扯一下这些关键字(说的不好或者不对的地方望大家能够指正)
要搞明白这三种关键字首先我们需要了解作用域
作用域就是变量与函数的可访问范围,作用域决定了代码区块中变量与其他资源的可访问性(可见性),在ES6之前,只存在全局作用域和局部作用域。ES6之后,出现了块级作用域。
全局作用域顾名思义就是作用域是全体即所有脚本与函数均能访问到,函数之外声明的变量就是全局变量
var name = "WDY";
function my(){
//里面可以调用name
}
局部作用域顾名思义就是作用域是局部即不是所有均能访问,函数之内的声明就是局部作用域
function my(){
var name = "WDY";
}
//不可访问name
由最近一对包含花括号界定{} 即if块,while块,function块,甚至是单独的块
if(true){
let name = "WDY";
}
//外部不可访问
while(true){
let name = "WDY";
}
//外部不可访问
function sayHi(){
var m = "Hi";
}
sayHi();
console.log(m) //报错,不可访问
//这也表示局部变量在函数退出时就被销毁了
使用var关键字声明的变量会自动提升到函数作用域顶部
function sayName(){
console.log(name);
var name = "WDY";
}
sayName(); //undefined
//!!注意变量提升意味着不会报错而是输出undefined,虽然提升了,但是不会读到值,所以不会输出WDY
//即可以后定义变量,在函数中它相当于在顶部命名即
function sayName(){
var name = "WDY";
console.log(name);
}
function sayName(){
console.log(name);
let name = "WDY"; //报错
}
if(true){
var name = "WDY";
console.log(name); //WDY
}
console.log(name); //WDY
if(true){
let name = "WDY";
console.log(name); //WDY
}
console.log(name); //报错:name没有定义
var name;
var name; //可行
let name;
let name; //报错
let name = "WDY";
console.log(name); //WDY
if(true){
let name = "王大宇";
console.log(name); //王大宇
}
var name = "WDY";
console.log(window.name); //WDY
let name = "WDY";
console,log(window.name); //undefined
const name; //×
const name = "WDY";
name = "傻子"; //×
const P1 = {};
p1 = {} //×
const p1 = {};
p1.name = "WDY";
console.log(p1.name);
//如果想让整个对象都不能修改可以使用Object.freeze(),不会报错,但不会成功
const p1 = Object.freeze({});
p1.name = "WDY";
console,log(p1.name); //undefined
//在循环中迭代变量时使用三者
for(var i = 0; i < 5; i++){
console.log(i); //1,2,3,4,5
}
console.log(i); //5
for(let i = 0; i <5; i++){
console.log(i); //1,2,3,4,5
}
console.log(i); //未定义
for(const i = 0; i < 5; i++){
console.log(i); //5,5,5,5,5
}
for(const i of [1,2,3,4,5]){
console.log(i); //1,2,3,4,5
}
JavaScript共有7中数据类型,其中,6种为简单数据类型(原始类型),他们是:Undefined,Null,Number,String,Boolean,Symbol(符号<为ES6新增类型>)。还有一种复杂数据类型(引用类型):Object。
其中6中简单数据类型属于原始值1种复杂数据类型属于引用值。在讨论数据类型之前,小王现在这里说一下这两种不同类型的数据。
保存原始值的变量是按值访问的,而引用值是保存在内存中的对象。
当我们操作原始值时,我们操作的就是存储在变量中的实际值,而当我们操作引用值时,JavaScript不允许直接访问内存的位置,因此我们不能直接操作对象本身所在的内存空间而是操作对该对象的引用。
我认为,这两种类型的区别在变量复制方面的得到了充分地体现:
对于原始值,复制之后与复制之前是完全独立的,而对于引用值,复制后的值与复制之前的值指向同一内存空间,所以两者相当于铁索连环啦哈哈哈。
接下来让我们进入今天的正题:
undefined即未定义的,其效果如字面意思,当我们使用var/let声明一个变量但未给其赋值时,该变量即为undefined(!注意const可不兴这的搞啊,使用const的前提就是声明的同时必须给其赋值),当然我们也可以给一个变量赋值为undefined但其效果等同于只声明而不赋值:
let test;
console.log(test); //undefined
let test = undefined;
console.log(test); //undefined
对于为声明的变量,其返回也是undefined
null即空的,其值表示一个空指针对象,如果我们声明一个变量但未确定给其赋何值时,我们可以将null赋给他,这样当后面我们需要知道这个是否被声明时,只要将其与null比较或者看他数据类型即可,undefined不行吗?undefined不行,因为为声明的值其返回值也可能是undefined。
布尔值,只有两个值true和false对于这两个值,有两点需特别注意:
布尔值可以通过Boolean()将布尔类型与其他数据类型联系起来:
数据类型 | true | false |
---|---|---|
String | 非空字符串 | “” |
Number | 非0值 | 0/NaN |
Object | 任意对象 | Null |
Undefined | undefined | |
Null |
不同于其他语言,JavaScript的整数和浮点数均为Number,但其存储时使用的内存空间大小不同,存储浮点值使用的内存空间是存储整数值得两倍,所以你懂得(不是很必要的情况就定义为整数)
先说整数:
整数可以由二进制,八进制(0<但是在严格模式下是微小的>),十进制,十六进制(0x)表示。
let number1 = 070; //八进制的56
let number2 = 079; //无效八进制,会被当做79
let number3 = 08; //无效八进制,会被当做8
let number4 = 0xA; //十六进制10
let number5 = 0x1f; //十六进制31
浮点数当小数点后面全为0时会自动转换为整数处理,科学计数法由e表示
千万注意在JavaScript中0.1+0.2 = 0.30000000000000004而不是0.3所以不要测试特定的浮点值
let number1 = 1.68;
let number2 = 0.1356;
let number3 = .123;
let number4 = 1.0; //当成1处理
还有一个特殊的数值叫NaN即不是数值(Not a Number)用于表示本来要返回数值的操作失败了。
0/0; //NaN
涉及NaN的所有操作始终返回NAN。
注意我不是我即NaN不等于NaN
console.log(NaN == NaN); //false
这里有一个方法isNaN()~~(是NaN吗?)~~用于帮我们判断一个值是不是数值。
不仅Boolean类型提供了与其他数据类型联动的方法,Number类型也能与其他数据类型联动Number():
数据类型 | |
---|---|
Boolean | true转换为1,false转换为0 |
Number | 直接返回 |
null | 0 |
undefined | NaN |
String | 空转换为0 |
只包含数值,返回数值 | |
除了数值还包含其他字符返回NAN |
let number1 = Number(true); //1
let number2 = Number(10); //10
let number3 = Number(""); //0
let number4 = Number(null); //0
let number5 = Number(undefined); //NaN
let number6 = Number("001"); //1
不仅仅是Number(),parseInt()也可以进行转换并且更为常用
let Number1 = parseInt(true); //NaN
let Number2 = parseInt(10); //10
let Number3 = parseInt(""); //NaN
let Number4 = parseInt(null); //NaN
let Number5 = parseInt(undefined); //NaN
let Number6 = parseInt("001"); //1
可以看出,Number()与parseInt()对于一些类型的转换还是有些许区别的。
此外parseInt()对于Number类型的转化也是杠杠的:
let number1 = parseInt("0xA"); //10为十六进制数
let number2 = parseInt("123木头人"); //123
let number3 = parseInt(3.14159) //3 碰到非数值字符会停止
//也可以接收两个参数,第二个参数指进制数
let number4 = parseInt("A",16); //10
let number5 = parseInt("10",2); //2 按二进制解析10
let number6 = parseInt("10",8); //8 按八进制解析10
不仅仅有parseInt(),parseFloat()也同样存在,但是parseFloat()只能解析十进制值,因此只传一个参数就可以了。
字符串数据类型,可以用单引号(’)双引号(")反引号(`)(好东西模板字符串)表示,但开头和结尾的引号必须是同一种引号。
let name = 'WDY';
let name = "WDY";
let name = `WDY`;
字符字面量
字面量 | 含义 |
---|---|
\n | 换行 |
\t | 制表 |
\b | 退格 |
\r | 回车 |
\f | 换页 |
\ | 反斜杠 |
’ | 单引号 |