文 / 景朝霞
来源公号 / 朝霞的光影笔记
ID / zhaoxiajingjing
图 / 自己画
❥❥❥❥点个赞,让我知道你来过~❥❥❥❥
0 / JS 中的数据类型的一些细节点
(1)JS中的数据类型
基本数据类型
1、 string
,可以用双引号、单引号、反引号
2、 number
,比如:值有123/1.2/NaN/Infinity/-Infinity...
3、 boolean
,值为true/false
4、 null
,值为null
5、 undefined
,值为undefined
6、 bigint
7、 symbol
,用于创建唯一值
引用数据类型
1、 object
例如:
① {}
普通对象
② []
数组对象
③ 日期对
④ 正则,比如:/^\\d+$/
⑤ ......
2、 function
① 普通函数
② 构造函数
③ 箭头函数
④ 生成器函数
⑤……
(2)number 的一些细节
number
类型的值有:
1、正数、负数、零、小数......
2、NaN
not a number 不是一个有效数字,但是它是number
类型的
xxx,你不是一个人。不是一个人,那是什么都有可能了
① NaN
和 NaN
本身不相等,和其他值也不相等
② isNaN(vlaue)
检测当前值是否不是一个有效数字,不是有效数字返回true;反之,是有效数字返回false
③ Object.is(NaN, NaN)
结果是true
,它的内部做了特殊处理
3、Infinity
无限大 -Infinity
无限小
console.log(typeof NaN); //=> 'number'
console.log(typeof Infinity); //=> 'number'
console.log(NaN == NaN); //=> false
console.log(NaN === NaN); //=> false
console.log(Object.is(NaN, NaN)); //=> true
△ NaN
把其它数据类型值转换为number
类型:
1、显式转换:Number(vlaue)
或者 parseInt(value)/parseFloat(value)
他们底层处理的规则不一样
2、隐式转换(逻辑用的是Number(value)
的)
① 数学运算
② 基于==
比较的时候
③ isNaN(value)
④ ....
(3)字符串的一些细节点
string
字符串:单引号、双引号、反引号,里面的内容都是字符串
其它值转换为字符串:
1、显式转换:String(value)
或者(vlaue).toString()
涉及到数据类型检测,后面再说
2、隐式转换:加号除了数学运算,还会产生字符串拼接
+ 加号是斜杠青年
let n = '10',
m = 10;
console.log(10 + n);
console.log(+n);
console.log(++n);
let obj = {};
console.log(10 + obj);
console.log(10 + new Number(10));
console.log(10 + {id:'zhaoxiajingjing'});
△ 结果是多少?
+
作为斜杠青年,本职工作是数学运算符,还斜杠担任了字符串拼接的工作,那它什么时候切换角色呢?
+
只有一边有内容时:比如+n
,把值转换为数字;++n/n++
也会把值转换为数字,然后再进行前置/后置自增
的运算
+两边都有内容时:
1、"+
" 有一边出现了字符串,就会变成字符串拼接
2、"+
" 有一边是对象,则也可能会成为字符串拼接:
△ 图1.1_"+"作为一枚斜杠青年
其中:①③得到的是数字10,原因是:{...}
没有参与运算,浏览器认为这是一个代码块,计算的是+10
而:console.log({}+10)
有一个括号把{}+10
包起来了,它会认为这是一个整体再进行运算
那么,对象在做数学运算时的底层机制:
(1)检测对象的Symbol.toPrimitive
【primitive [ˈprɪmətɪv] n.原始的】 这个属性值,如果有则基于这个值进行运算,如果没有,走下一步
(2)检测对象的valueOf()
这个值【原始值/基本类型值】,如果有则基于这个值进行运算,如果不是原始值,走下一步
(3)获取对象的toString()
把其变为字符串 => 如果是" +
"处理,则看到字符串了,变为字符串拼接
(4)如果最后就是想要得到的数字,则再把字符串转换为数字即可
let obj = {
[Symbol.toPrimitive]:function (){
return 10;
}
};
console.log(10 + obj); //=> 20
△ 对象获得的是数字
而, console.log(10 + new Number(10))
的结果就是数字20
,是因为new Number(10).valueOf()
获得的原始值就是数字10
∴ 答案是:
let n = '10',
m = 10;
console.log(10 + n); //=> 字符串拼接:'1010'
console.log(+n); //=> 把值转换为数字:10
console.log(++n); //=> 把值转换为数字,在前置自增:11
let obj = {};
console.log(10 + obj); //=> '10[object Object]'
console.log(10 + new Number(10)); //=> 20
console.log(10 + {id:'zhaoxiajingjing'}); //=> '10[object Object]'
△ + 是一枚斜杠青年
那么,请问:i=i+1
i+=1;
++i/i++
这三个一样吗?
其中:i=i+1
和i+=1
是一样的;++i/i++
大部分情况是与前面的一样的。
如果i
的值是字符串则不一样了:
i=i+1
i+=1
会处理为字符串拼接
++i/i++
先把值转为数字,再进行前置/后置累加
(4)symbol 唯一值
API:https://developer.mozilla.org...
Symbol()
:创建唯一值
Symbol()
函数会返回symbol
类型的值
new Symbol()
报错:Uncaught TypeError: Symbol is not a constructor
△ 图1.2_symbol类型
Symbol.toPrimitive
Symbol.toPrimitive
是一个内置的Symbol值,它是作为对象的函数值属性存在的,当一个对象转换为对应的原始值时,会调用次函数
let obj = {
[Symbol.toPrimitive]:function (hint){
console.log(hint); // hint 取值:"number/string/default"
return 10;
}
};
console.log(10 + obj); //=> 20 hint输出 'default'
Number(obj); //=> hint输出 'number' obj的原始值 10
String(obj); //=> hint输出 'string' obj的原始值 '10'
△ Symbol.toPrimitive
(5)BigInt 大数
△ 图1.3_bigint
2 / 栈内存 Stack & 堆内存 Heap
(1)题很简单
var a = 12;
var b = a;
b = 13;
console.log(a);
-----------------
var a = {n: 12};
var b = a;
b['n'] = 13;
console.log(a.n);
-----------------
var a = {n: 12};
var b = a;
b = {n: 13};
console.log(a.n);
△ 做题很简单,关键要了解里面的机制
(2)第一题
我们新建一个index.html
文件,在里面引入1.js
文件,然后打开浏览器访问index.html
文件时,浏览器会渲染JS
那么JS可以执行的环境:
① 浏览器:浏览器的内核=>JS渲染引擎
② 移动端Hybrid混合APP => webview 基于 webkit内核
③ Node
④ ……
浏览器会专门开辟一块内存来执行JS代码 => 栈内存,执行环境栈ECStack(Execution Context Stack)
会有一个供全局代码执行的区域:全局执行上下文,EC(G) (Execution Context Global)
形成上下文的目的:区分不同区域的代码执行
比如:全局执行上下文、函数执行上下文……
执行上下文会进入到执行环境栈中运行,当浏览器关闭时全局执行上下文就会出栈销毁
△图1.4_第一题简图
var a = 12;
第一步:创建值
① 基本值直接存到栈内存中
② 引用值是单独开辟一块新的内存来存储
第二步:声明变量 declare
第三步:变量和值关联在一起,定义defined
∴ var c;
只进行变量声明declare,并未定义undefined,console.log(c);//=>undefined
(3)第二题
△图1.5_第二题简图
创建值:
1、 基本数据类型直接存储到栈里面
2、 引用数据类型:
(1)单独开辟一块内存heap 堆内存
(2)每一个堆内存都有一个16进制地址 JS中不能获取到这个地址,16进制以0x
开头
(3)把键值对分别存储到堆中
(4)把16进制地址放到栈中存储:方便后期变量的关联
引用数据类型:变量操作的都是对 堆内存地址 的引用
b['n']=13;
① b 基于地址0x000001
找到堆内存
② 把堆内存中属性名为n
的属性值改为13
(4)第三题
△图1.6_第三题简图
(5)堆栈内存作用
栈内存or堆内存,都是浏览器从计算机中分配出来的内存,开辟的越多,电脑性能越慢 => 性能优化:内存优化
栈内存作用:代码执行和存储基本类型值
堆内存作用:存储引用数据类型
3 / 作业
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x);
console.log(b);
△ 第一题
一般情况下:a=b=xxx
的运算顺序是:
① b=xxx
② a=xxx
但是,当a.x=b=xxx
时,a.x
中的"点
"是成员访问,它的运算符优先级很高:
① a.x = xxx
② b = xxx
var x = [12, 23];
function fn(y) {
y[0] = 100;
y = [100];
y[1] = 200;
console.log(y);
}
fn(x);
console.log(x);
△ 第二题
- end -
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。