引言
0基础进互联网大厂系列持续更新,今天用简单、实用的案例深入浅出地了解JS的数据存储。废话不多说,我们直接开始!
基础篇——数据类型(原始类型和引用类型)
原始类型(7种)
字符串类型(string)
下面这份就是简单的声明一个字符串变量。
注意:
1、不要吃饱了没事干写第二行这种代码,因为它和第三行代码没有区别
2、使用单引号和双引号都是可以的
3、字符串也有.length方法,得到字符串长度
4、你有没有发现输出的内容颜色好像不一样,没啥好解释,字符串是灰色的,其他类型是黄色的(注意要在终端手动node xx.js才能有这种颜色效果,使用code Runner插件是没有颜色区分的)
let str = "hello" //String
console.log(str.charAt(0));//索引取值
console.log(str[0])//索引取值
console.log(str.length);//长度
数字类型(number)
let num = 123; //Number
console.log(num)
console.log(num.toString())//转化为字符串
布尔类型(Boolean)
提一嘴:布尔类型就很简单,只有true和false,但是在实际上,我们应该判断是否非空,0属于空,如果在一个判断是否非空里,内容非空,注意是符合条件的,不是非要true 或者 1这些数字非0数字。
let bool = true; //Boolean
console.log(bool)
console.log(bool.toString())//转化为字符串
未定义类型(undefined)
这是一种特殊的类型:我们在第2天的文章聊JS预编译时,变量都会被赋值undefined,那么我问你,这些变量的类型是什么?是的,就是undefined类型。
let un = undefined;
console.log(un)
空类型(null)
let nul = null;
console.log(nul)
以上,都是通过字面量声明变量
以下,通过构造函数来声明变量
通过关键字new来创建变量
let str2 = new String("hello"); //String
console.log(str2)
let num2 = new Number(123); //Number
console.log(num2)
你肯定要问我,这和字面量声明变量有什么区别吗?
废话不多讲,区别:
1、通过字面量声明的变量,类型是原始类型,放在常量池中,也就是栈内存中,如果已经有了该变量值,则无论声明多少个,都是指向该变量值,不会重复创建。
let str1 = "hello"
let str2 = "hello"
console.log(str1 == str2);
console.log(str1 === str2);
2、 使用构造函数声明的变量存储在堆内存中,属于引用类型。变量的内容相同,地址不一样。
let str2 = "hello"
let str3 = new String("hello"); //String
console.log(str3 == str2);
console.log(str3 === str2);
null undefined 无法通过构造函数声明
let nul2 = new Null(); //Null
console.log(nul2)
ES6新增类型
符号类型(symbol)
看一份代码,你就懂了它的核心特性:唯一性
let s1 = "hello"; //字符串
let s2 = "hello"; //字符串
console.log(s1 == s2) //true
let sy = Symbol("123"); //被Symbol修饰过的字符串
let sy2 = Symbol("123"); //被Symbol修饰过的字符串
console.log(sy == sy2) //false
大整数类型(bigint)
看这份代码:先不管num是否计算正确,在它+1之后,值未变,就说明了超出了原始类型number的范围,在当今这个数据爆炸的时代,是很常见的事情
所以,我们该如何处理?
简单了解一下:在数字后加个n,就代表bigint类型,注意,bigint类型只能和bigint类型之间运算,不能和原始类型number进行运算。
进阶篇——对象里的数据存储
案例一:
好的,我们先来看一份代码:
告诉我,obj里的age执行完代码后是多少?
对的,还是18
因为age++压根访问不到obj里的age
正确的做法是obj.age++
let obj = {
name: "zhangsan",
age: 18,
headth: 100,
say: function () { //Function
console.log("hello");
},
drink: function () { //Function,
console.log("drink");
headth--
}
}
age++;
第二个问题:请问打印的是什么?
是 99 还是 100 还是什么?
let obj = { //Object
name: "zhangsan",
age: 18,
headth: 100,
say: function () { //Function
console.log("hello");
},
drink: function () { //Function,
console.log("drink");
headth--
}
}
obj.drink()
console.log(obj.headth);
输出结果:
先打印drink后出现以下报错,并不会打印100出来
为什么会出现这种情况?
很明显,函数里的headth并没有指明是obj里的
函数drink的外部作用域是全局,而不是obj,所以不违背我们之前聊的——内部变量一定能够访问外部作用域
所以,我们需要怎么样修改代码?
改成:obj.headth--
也可以用this,但不急,我们后面会细聊this,毕竟是0基础系列文章,我们一步步来。
还有问题,那么我问你,这份代码的输出结果又是什么?
let obj = { //Object
name: "zhangsan",
age: 18,
headth: 100,
say: function () { //Function
console.log("hello");
},
drink: function () { //Function,
console.log("drink");
obj.headth--
}
}
meiGirl = "张若男"
obj.meiGirl = "lisi"
console.log(obj.meiGirl)
不知道你答对了没有?这是因为meiGirl在这里是字符串,并不是变量,对象直接将meiGirl当作属性添加进去了。
如果我将obj.meiGirl = "lisi"
替换为obj[meiGirl] = "xxx"
,console.log(obj.meiGirl)
替换为console.log(obj[meiGirl])
请问输出的是什么?
我猜你大概率是答对了!
对象删除属性:delete obj.drink
案例二
这份代码,应该不陌生,看过我之前的文章,了解JS执行机制,你能直接说出打印的内容。
function fn() {
var a = 2;
var b = a;
a = 1;
console.log(a);//1
console.log(b);//2
}
fn()
那么,请问,这份代码的输出结果是什么?
function fn() {
var a = { name: "zhangsan" };
var b = a;
a.name = "lisi";
console.log(a);
console.log(b);
}
fn()
如果你犹豫了,那就听我胡说八道一番
我们进行带入JS执行的视角
核心:创建一个对象,在栈内存里,仅仅是保存了该对象在堆内存里的地址
这里,变量a,b的值都是#001,所以访问的都是同一个对象,所以打印的东西也都是相同的,并且都是lisi
案例三(考考你)
请问这份代码的输出结果是什么呢?
答案在最下面,都看到这里了,我相信你是会的,可以尝试自己做做(一脸肯定)
function foo(person) {
person.age = 20
person = {
name: '李四'
}
return person
}
let p1 = {
name: '张三',
age: 18
}
let p2 = foo(p1)
console.log(p1);
console.log(p2);
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏
防止立马看到答案霸屏