JavaScript01 --- 变量与数据类型

变量

声明变量的三个关键字:var、let、const

var关键字:

例如: var messgae = “abc”;

这行代码定义了一个名为message的变量。可以用它保存任何类型的值。不初始化的情况下,变量会保存一个特殊值undefined。

function test() {
	var message;
    console.log(message);
}
test();

初始化变量之后,并不会将其标识为字符串,只是简单的赋值。在之后的操作中,既可以改变值,也可以改变值的类型(但不推荐)。

var声明作用域:

var操作符定义的变量会成为包含它的函数的局部变量。当使用var在一个函数内部定义一个变量,那么该变量就会在函数退出时被销毁。

function test(){
    var message = "abc";
}
test();
console.log(message); //报错
let关键字:

let和var的作用差不多,但也有非常重要的差别。

1、作用范围不同:let的声明范围时块作用域,而var声明的范围是函数作用域。

function test() {
    if(true){
        var message ="abc";
        console.log(message); //abc
    }
    console.log(message); //abc
}
test();
function test() {
    if(true){
        let message ="abc";
        console.log(message); //abc
    }
    console.log(message); //Uncaught ReferenceError: message is not defined
}
test();

2、暂时性死区:let声明的变量不会在作用域中被提升。如果用let关键字声明,则不能以任何方式来引用未声明的变量。在let声明之前的执行瞬间被称为“暂时性死区”,在此阶段引用任何后面才声明的变量都会抛出ReferenceError异常。

function test() {
    console.log(name); // undefined
    var name = "zhangsan";
    console.log(name); // zhangsan

    console.log(sex); // ReferenceError
    let sex = "male";
    console.log(sex);
}
test();

3、全局声明:var声明的变量会成为window对象的属性,而let在全局作用域中声明的变量不会。

4、for循环中的let声明:如果for循环的迭代变量使用var关键字,那么该变量就会渗透到循环体外部。如果用let关键字修饰,则该迭代变量的作用域就仅限于for循环块内部。

function test() {
    for(let i = 0; i < 5; ++i);
    console.log(i); // ReferenceError
}
test();
function test() {
    for(var i = 0; i < 5; ++i);
    console.log(i); // 5
}
test();
const关键字:

const的行为基本与let相同,唯一一个重要区别就是声明变量时必须同时初始化变量,并且不能修改。一旦修改就会导致程序报错。

同时,const也不允许重复声明,作用域也是块。

注:const声明的限制只适用于它指向的变量的引用。如果引用的是一个对象,那么修改对象内部的属性并不违反const的限制。

声明风格:

1、限制自己修饰变量时只用let和const来提高自己的代码质量,因为变量有了明确的作用域、声明位置以及不变的值。

2、使用const定义变量可以强制性保持变量值不变,也可以让IDE提前发现不合法的操作。一般都优先使用const来定义变量,如果发现该变量的值需要修改,再将const改为let即可。

数据类型:

原始类型:Undefined、Null、Boolean、Number、String、Symbol

typeof操作符:用来确定任意变量的数据类型。
(1)Undefined:表示值未定义

当使用var或let声明了变量但没有初始化时,就相当于给变量的值为Undefined。当与undefined的字面值比较时,二者是相等的。

function test() {
    let name;
    console.log(name == undefined); // true
    name = undefined;
    console.log(name == undefined); // true
}
test();

增加undefined这个特殊值的目的就是为了明确空指针对象(null)和未初始化变量的区别。

(2)Null:空对象指针

当给typeof传一个null时会返回“object”。

function test() {
    let person = null;
    console.log(typeof person); // object
}
test();

在定义将来要保存对象值的变量时,建议使用null来初始化,不要使用其他值。之后只需要看这个变量的值是不是null就可以判断是否被重新赋予了一个对象的引用。

(3)Boolean:布尔值

使用非常频繁。Boolean有两个字面值:true和false。这两个布尔值与数值不一样,所以true不等于1,false不等于0。

虽然布尔值只有两个,但其他类型的值都有相应布尔值的等价形式。

数据类型转换为true的值转换为false的值
Booleantruefalse
String非空字符串空字符串
Number非零数值(包括无穷)0、NaN
Object任意对象null
UndefinedN/A(不存在)undefined
(4)Number:整数与浮点值

整数也可以用八进制或十六进制来表示。对于八进制而言,第一个数字必须是0,然后是相应的八进制数字。如果有数字超出了应有的范围,则会忽略掉前缀的0,后面的数字会被当做十进制的整数。

function test() {
    let num;
    num = 10;
    console.log(num); //10
    num = 010;
    console.log(num); //8
    num = 080;
    console.log(num); //80
}
test();

对于十六进制而言,数值的前缀必须是“0x”,十六进制数字中的字母大小写均可。

由于内存受到限制,所以Number类型可以表示的最小数值保存在了Number.MIN_VALUE中,最大值保存在了Number.MAX_VALUE中。如果某个计算得到的数值结果超过了JavaScript可以表示的范围,那么该数值会自动转化为一个无穷值(Infinity)。任何无法表示的负数都用-Infinity表示,任何无法表示的整数都用Infinity表示。

NaN(Not a Number):用于表示要返回数值的操作失败了(不是抛出错误)。例如,当除法运算中,0被当作了除数导致代码中止执行。0,+0,-0相除会返回NaN。如果分子是非0值,分母是0,则会返回无穷大。
function test() {
    console.log(0 / -0); // NaN
    console.log(5 / 0);  // Infinity
    console.log(5 / -0); // -Infinity
}
test();

注意:任何涉及NaN的操作始终返回NaN。NaN不等于包括NaN在内的任何值。

function test() {
    console.log(NaN == NaN);  // false
    console.log(NaN === NaN); // false
}
test();
(5)String:字符串

将一个值转换为字符串,首选toString()方法。这个方法唯一的用途就是返回当前值的字符串等价物。

toString()方法可见于数值、布尔值、对象和字符串。null和undefined没有toString方法。

多数情况下,toString()方法不接受任何参数。在对数值调用这个方法时,toString()方法可以接受一个底数参数。默认情况下,用十进制表示。

function test() {
    let num = 10;
    console.log(num.toString());   // 10
    console.log(num.toString(2));  // 1010
    console.log(num.toString(7));  // 13
    console.log(num.toString(12)); // a
}
test();
(6)Symbol:符号

符号是原始值,且符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。

调用Symbol()函数时,也可以传入一个字符串参数作为对符号的描述。但是,这个字符串参数与符号定义或标识完全无关。

function test() {
    let symbol1 = Symbol();
    let symbol2 = Symbol();
    console.log(symbol1 == symbol2); // false
    let symbol3 = Symbol("abc");
    let symbol4 = Symbol("abc");
    console.log(symbol3 == symbol4); // false
}
test();
Symbol()不能被用作构造函数。这样是为了避免创建符号包装对象。如果想使用符号包装对象,需借用Object()函数。
function test() {
    let boolean = new Boolean();
    console.log(typeof boolean);  // object
    let string = new String();
    console.log(typeof string);   // object
    let number = new Number();
    console.log(typeof number);   // object
    let symbol = Object(Symbol());
    console.log(typeof symbol);   // object
    let symbol2 = new Symbol();
    console.log(typeof symbol2);  // Uncaught TypeError: Symbol is not a constructor
}
test();

如果运行时的不同部分需要共享和重用符号实例,那么可以用一个字符串作为键,在全局符号注册表中创建并重用符号。

为此,需要使用Symbol.for()方法。

function test() {
    let symbol1 = Symbol.for("abc");
    console.log(typeof symbol1);  // symbol
    let symbol2 = Symbol.for("abc");
    console.log(symbol1 === symbol2);  // true
}
test();

即使采用相同的符号描述,在全局注册表中定义的符号和使用Symbol()定义的符号也并不等同。

function test() {
    let symbol1 = Symbol.for("abc");
    let symbol2 = Symbol("abc");
    console.log(symbol1 == symbol2);  // false
    console.log(symbol1 === symbol2); // false
}
test();

全局注册表中的符号必须使用字符串键来创建,因此作为参数传给Symbol.for()的任何值都会被转换为字符串。

使用Symbol.keyFor()来查询全局注册表,这个方法接收符号,返回该全局符号对应的字符串键。如果不是全局符号,则返回undefined。

function test() {
    let symbol1 = Symbol.for("abc");
    console.log(Symbol.keyFor(symbol1));  // abc
    let symbol2 = Symbol("abc");
    console.log(Symbol.keyFor(symbol2)); // undefined
}
test();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值