JavaScript高级程序设计笔记——数据类型

基本数据类型

JavaScript 有5种基本数据类型:Undefined、Null、Boolean、Number 和 String。

Undefined类型

Undefined 类型只有一个值 undefined,如果使用var定义的变量未初始化值,其默认的值为 undefined。

var str;
console.log(str); // undefined

Null类型

Null 类型只有一个值 null,表示空对象,所以typeof操作 null 值的结果是"object"。

Boolean类型

Boolean 类型有两个值 true 和 false,分别表示"是"和"否"。

Number类型

Number 类型取值是所有数值,不区分整型数值和浮点型数值,JavaScript 采用 IEEE-754 浮点数表示法,这是一种二进制表示法,可以精确地表示分数,但是不能精确表示类似0.1这样简单的数字,也就是说,在进行涉及浮点数的计算时,会出现类似以下问题:

var x = .3 - .2;
var y = .2 - .1;
console.log(x == y); //false
console.log(x == .1); //false
console.log(y == .1); //false

如果一定要进行浮点型数值计算,可以将相加的两个浮点数转为整数,最后再将相加结果转为浮点数:

// 普通的浮点计算
var sum1 = 0.1 + 0.2;
console.log(sum1); // 0.30000000000000004
console.log(sum1 === 0.3); // false

// 特殊处理的浮点计算
var sum2 = 0.1 * 10 + 0.2 * 10;
console.log(sum2 / 10); // 0.3
console.log(sum2 === 0.3); // true

可以使用指数记数法表示浮点型直接量,即在实数后跟字母 e 或 E,后面再跟正负号,其后再加一个整型的指数。这种记数方法表示的数值,是由前面的实数乘以10的指数次幂。例如3.14e2表示的就是314。

JavaScript 定义的数值还可以是十进制、八进制和十六进制值,定义的所有进制的值最终都会被转换为十进制值。

var n1 = 10; // 十进制,值10
var n2 = 0o10; // 八进制,值8
var n3 = 0x10; // 十六进制,值16

Number 有一个特殊值 NaN,表示一个本来要返回数值的操作值未返回数值的情况。

console.log(Number('a') + 10); // NaN

判断一个值是否为 NaN 只能通过isNaN()方法。

console.log(isNaN('a')); // false
console.log(isNaN(1 + 'n')); // true

注:NaN == NaN返回 false。

String类型

声明字符串:var str = ‘WJT’。

字符串中可以嵌入字符字面量,例如:var str = ‘WJT\nHello’,其中,\n表示换行符。

字符串属于类数组对象(类数组对象的特点:可以通过索引号访问指定位置元素,有 length 属性):

var l = 'ABC'.length;
console.log(l); // 输出3

可以使用+号拼接字符串:var str = ‘AB’ + ‘C’。

使用字符串的concat()方法也可以拼接字符串:var str = ‘A’.concat(‘B’),这句代码返回一个由"A"拼接"B"形成的新字符串——“AB”。

引用数据类型

Object类型

Object 类型(对象)其实是一个键值对集合,可以直接使用花括号创建对象,然后定义属性或方法。所有引用类型都基于 Object 类型。

var obj = {
    name: 'WJT', // 定义属性

    // 定义方法
    sayHello: function(name) {
        console.log('Hello, ' + name);
    }
};

obj.id = 123; // 外部定义属性
console.log(obj.name); // 访问属性,输出: "WJT"
obj.sayHello('xxx'); // 调用方法,输出: "Hello, xxx"

Date类型

Date类型就是日期时间的访问操作接口,使用new关键字可以创建一个Date实例对象。

var time = new Date();

将日期对象转为数值可以使用"+"号,也可以使用valueOf()方法获取,本人比较推荐使用第二种:

var time = new Date();
console.log(+time); // 1533089048343
console.log(time.valueOf()); // 1533089048343

Date 日期对象常用 API:

  1. dateObj.getFullYear():返回创建时的年份;
  2. dateObj.getMonth() + 1:从0开始计起,返回0实际上是一月;
  3. dateObj.getDate():返回创建时的日期;
  4. dateObj.getHours():返回创建时的小时;
  5. dateObj.getMinutes():返回创建时的分钟;
  6. dateObj.getSeconds():返回创建时的秒数;
  7. dateObj.getMilliseconds():返回创建时的毫秒数;
  8. dateObj.getDay():返回创建时的星期(数值0-6)。

函数实现:返回"2018-08-01 10:48:24 Wed"格式的日期字符串。

function getCurrentTime() {
    var time = new Date();
    var ary = [];
    ary.push(time.toISOString().substr(0, 10));
    ary.push(time.toTimeString().match(/[0-9]+:[0-9]+:[0-9]+/)[0]);
    ary.push(time.toUTCString().match(/\w+,/)[0].slice(0, -1));
    return ary.join(' ');
}

iOS 日期转换的坑点:

var date1 = (new Date('2021-03-05 17:40')).valueOf();
console.log(date1); // iOS上返回NaN,其他设备返回1614937200000

var date2 = (new Date('2021/03/05 17:40')).valueOf();
console.log(date2); // 所有设备都能返回1614937200000

Array类型

创建数组有两种方式:使用new Array()和使用数组字面量表示法。JavaScript 数组不限制数组元素的数据类型保持统一,一个数组可以包含各种类型的值。

数组实例对象具有一个 length 属性返回数组的元素个数,length 属性可以手动修改,例如想要重置一个数组只要将 length 属性值设为0。数组元素可以通过"[]"加索引号访问。

var arr1 = new Array(5); // 创建一个包含5个空值的数组
var arr2 = new Array('a', 1, true); // 创建数组并填充元素
var arr3 = ['a', 1, true]; // 推荐使用数组字面量写法

console.log(arr3.length); // 输出: 3
console.log(arr3[0]); // 输出: "a"
console.log(arr3[arr3.length - 1]); // 访问最后一个元素: true

arr3.length = 0;
console.log(arr3[0]); // 输出: undefined

Math类型

Math类型包含了一些常用于数学计算的属性和方法,常用的属性常量有:Math.PI,即获取π的值:3.141592653589793。

Math.min(num1, …)和 Math.max(num1, …),接收一段数值参数,分别返回其中的最大值和最小值。

var num3 = 10;
var num4 = 5;
console.log(Math.min(num3, num4)); // 输出: 5
console.log(Math.max(num3, num4)); // 输出: 10

舍入方法:

1.Math.ceil(num):向上舍入;
2.Math.floor(num):向下舍入;
3.Math.round(num):四舍五入。

Math.random()用于获取大于等于0小于1的浮点数,获取a到b之间的整数使用语句:Math.floor(Math.random() * (b - a + 1) + a)。

var num7 = Math.floor(Math.random() * 10); // 获取大于等于0小于10的任意整数
var num1 = Math.floor(Math.random() * (10 - 5 + 1) + 5); // 获取大于等于5小于11(5到10之间)的任意整数

基本数据类型与引用数据类型的区别

两种类型的区别是:存储位置不同。

具体体现在:

●基本数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
●引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

深拷贝与浅拷贝

区分深拷贝与浅拷贝的方法,举个例子,A拷贝B,改变A的值,若B也跟着改变,则此拷贝过程为浅拷贝,否则为深拷贝。深拷贝和浅拷贝发生于引用数据类型,拷贝对象通常是 Object 或 Array。

内存存取原理

在进入深拷贝和浅拷贝主题前,先要了解下数据是如何存储到内存中的。

对于基本数据类型,数据名值都是存储于栈内存中,当进行复制操作时,栈内存会新开辟一个内存,正因如此,两者互不干预。

var a = 1;
var b = a;
console.log(a, b); // 1 1
b = 2;
console.log(a, b); // 1 2

可以看到,将 b 赋值为2,a 的值也不会变为2。

引用数据类型则不一样,当定义一个引用类型的数据时,栈内存会提供一个引用的地址指向堆内存中的值,当进行复制操作时,复制拿到的是引用的地址而不是真正的值,如果这个时候改变副本的某个值,直接改变的是堆内存中的值,这就导致引用此地址的另一个数据里的值跟着一起变,这就达不到深拷贝的效果。

如何实现深拷贝

实现深拷贝有以下两种方法:

1.使用递归(这里不考虑算法性能),示例代码如下:

function deepClone(obj) {
    var clonedObj = obj.constructor === Array ? [] : {};
    if (typeof obj === 'object') {
        for (var key in obj) {
            if (obj[key] && typeof obj[key] === 'object') {
                // 如果子元素为对象,则递归复制
                clonedObj[key] = deepClone(obj[key]);
            } else {
                // 非引用类型直接复制
                clonedObj[key] = obj[key];
            }
        }
    }
    return clonedObj;
}

var data1 = {
    name: 'xxx',
    grade: [100, 95, 90]
};
var data2 = deepClone(data1);
data2.grade = [60, 70, 80];
console.log(data1, data2); // {name:"xxx",grade:[100,95,90]} {name:"xxx",grade:[60,70,80]}

2.使用JSON.parse()和JSON.stringify()方法,这种方法比第一种方法简单的多,但是这种方法也有缺陷,那就是转化不了 Function、Date 等类型数据:

function deepClone(obj) {
    var clonedObj;
    var json;
    if (obj && typeof obj === 'object') {
        json = JSON.stringify(obj);
        clonedObj = JSON.parse(json);
    }
    return clonedObj;
}

var data1 = {
    name: 'xxx',
    grade: [100, 95, 90]
};
var data2 = deepClone(data1);
data2.grade = [60, 70, 80];
console.log(data1, data2); // {name:"xxx",grade:[100,95,90]} {name:"xxx",grade:[60,70,80]}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值