js堆栈、判断数据类型、toString和valueOf区别,类型转换、不同类型间的运算、判断相等

目录

数据类型

基本:栈/(闭包在堆)

ES5:null,undefined,number,string,boolean

ES6:symbol

ES10:bigint

引用:(栈中存储指针,指向堆中数据的起始地址)

ES5:Object,function,Array,Date,RegExp

改变Array的方法:进出*4,splice,sort,reverse,fill

Array:索引是非负整数(或字符串),基于连续内存

Map/set(有序):任何值类型都可以作为键/值,size,可迭代,删减优化

Object(无序):键:String、Symbol,JSON序列化JSON.stringify()和解析JSON.parse()

ES6:Promise(解决回调地狱),Proxy

Map:键/值对

WeakMap:键必须是对象或非全局symbol

ES14:Symbol 可作为 WeakMap 键

Set:任何值

WeakSet:值必须是对象或非全局symbol

new Proxy(target, handler)

ts

判断数据类型

字面量:数据固定值,不用构造函数创建

基本类型:不属于引用类型

引用string实例的属性、方法时:字面量string会临时转换为对象

引用类型:仍然是引用类型

运算符

typeof:判断 基本数据类型+ 广义函数(function、promise、箭头函数)

typeof null=Object 类型标签均为000

typeof NaN==Number:全局方法isNaN()

实例 instanceof 构造函数:判断原型链

方法

构造函数.prototype.isPrototypeOf(实例) :判断原型链

(数据).constructor === 数据类型:不包含继承类型

显示

toString,valueOf

除了null,undefined

基本数据类型、function,Array,RegExp:返回数据本身

引用数据类型

Object,(Weak)Map、(Weak)Set:[object 类型]

Date:...中国标准时间(ECMAScript规范定义的日期时间字符串格式)

valueOf:this 值转换为对象

toString:重写对象的类型转换

类型转换

Number

数字字面量:浮点数值

显式类型转换

Number(任意类型):任意类型->string、若string含非数字,会返回NaN

[num]为num

undefined、{} 为 NaN

null 、[]、''空字符串或仅包含空格的字符串、为 0

BigInt 抛出 TypeError,以防止意外的强制隐式转换导致精度损失

Symbol 抛出 TypeError  

Date:秒

前导和尾随的空格/换行符会被忽略

前导的数字 0 不会导致该数值成为八进制字面量

+ 和 - 是独立的一元运算符,后面不能跟空格

parseInt(string[,radix]):基数radix是2-36之间的整数

parseFloat(string):解析一个参数并返回一个浮点数,无法识别 0x 前缀

区别:pase类自动截断尾部非数字,Number不会截断

parseInt(string[,radix]):基数radix是2-36之间的整数

parseFloat(string):解析一个参数并返回一个浮点数

隐式转换:+str-,含boolean的相加

str - 1 //122

+str+1 // 124

str+1 // '1231'

String

显式类型转换

除了null/undefined.toString()  

String(任意类型) 

隐式转换:含str的相加

Boolean

显式类型转换

Boolean():0, ''(空字符串), null, undefined, NaN会转成false,其它都是true

隐式转换 :!!

比较

字符串:字符顺序(等长),长的大(短是长的前缀)

相加减:交换顺序后结果不变

num相加

null、undefined、boolean基本类型:转Number

obj、function、arr、Date等引用类型:转string

因为只有[]\[num]这两类特殊的数字才能转换为Number、所以为了统一,arr:转string优先于Number

num相减:能转number就转,不能则NaN

相等

全局属性 NaN :非数字的值,它与任何其他值(包括自身)都不相等

isNaN(string/Number/boolean/null)

Object.is(val0, val1):NaN等,±0不等

只能比较字面量,对象只会判为false

===、==:NaN不等、±0等

松散相等==(可自动转换类型) 和 严格相等===

比较的是内存单元的内容

对象传递是引用地址:判断对象相等,需要深度比较

set用===判断是否相等

对象判空

JSON.stringify(obj) == '{}'

Object.keys(obj).length==0


数据类型

基本:栈/(闭包在堆)

原始值(原始数据类型)

  • 非对象,无属性/方法

在原始值上访问属性时,自动将值装入包装临时对象(自动装箱行为)

  • 不可修改

不要将原始值本身与分配了原始值的变量混淆

let str = "hello";

// 尝试给字符串添加一个属性
str.foo = "bar";

console.log(str.foo); // 输出: undefined
console.log(str); // 输出: "hello"
  • 占用空间

基本数据类型占用空间、大小固定,通过值来访问,属于被频繁使用的数据

闭包中的基本数据类型变量是保存在堆内存里的,当函数执行完弹出调用栈后,返回一个内部函数的一个引用,这时候函数的变量就会转移到堆上,因此内部函数依然能访问到上一层函数的变量。

ES5:null,undefined,number,string,boolean

ES6:symbol

console.log(symbol2 === 42);
// Expected output: false

console.log(Symbol('foo') === Symbol('foo'));
// Expected output: false

ES10:bigint

let bnum=1684424684321231561n  //方式1:数组后加n
bunm=BigInt("1684424684321231561")//方式2:调用BigInt

引用:(栈中存储指针,指向堆中数据的起始地址)

二叉堆,引用数据类型占据空间大、大小不固定,如果存储在栈中,将影响程序的运行性能

引用数据类型会在栈中存储一个指针,这个指针指向堆内存空间中该实体的起始地址。

ES5:Object,function,Array,Date,RegExp

改变Array的方法:进出*4,splice,sort,reverse,fill
Array:索引非负整数(或字符串),基于连续内存

要求使用方括号表示法而不是点号表示法来访问以数字开头的属性

数组基于Object实现,属性名是字符串;隐式的 toString将数字索引自动转换成字符串

因此索引'2' !='02'

let myArray = [];
myArray[0] = "Apple";
myArray["asd"] = "Banana";
myArray["2"] = "Cherry";
console.log(myArray)//Array ["Apple", undefined, "Cherry"]
Map/set(有序):任何值类型都可以作为键/值,size,可迭代,删减优化

迭代:for in,for of,forEach

关联数组字典映射):每个键(通常是字符串)都与一个值关联

Object(无序):键:StringSymbol,JSON序列化JSON.stringify()和解析JSON.parse()

迭代:for in,

ES6:Promise(解决回调地狱),Proxy

Map:键/值对

底层优化

映射设置值时会将键和值添加到这两个数组的末尾。从而使得索引相对应

取/赋值,需要 O(n) 

强引用(哪怕不被引用了,也会阻止垃圾自动回收),导致内存泄漏

WeakMap:键必须是对象或非全局symbol

(此处的键值对都是对象)

当键被回收+值没被引用,则值回收

当值回收,不影响键

symbol是保证唯一的,并且不能被重新创建,和对象引用地址一样

非全局意味着有生命周期,可以被释放 对应着 对象不再被引用,然后被回收

ES14:Symbol 可作为 WeakMap 键
Set:任何值
WeakSet:值必须是对象或非全局symbol

weak弱引用对象,不被引用时会被回收,所以weakmap键和weakset值必须是对象

WeakMap因为获取键的列表会依赖于垃圾回收的状态

所以不允许观察其键的生命周期不允许枚举

new Proxy(target, handler)

target

包装target (对象/数组/函数甚/proxy对象)

handler

被代理对象上的自定义行为(定义一组处理函数(例如get、set)的对象)

const target = {
  notProxied: "original value",
  proxied: "original value",
};

const handler = {
//target:被代理者(就是上面的target)
//prop:被代理者的属性
//receiver:代理者 Proxy 或者继承 Proxy 的对象
  get: function (target, prop, receiver) {
    if (prop === "proxied") {
      return "replaced value";
    }
    return Reflect.get(...arguments);//调用原始对象上相同的属性,保持属性的原始值不变
  },
};

const proxy = new Proxy(target, handler);

console.log(proxy.notProxied); // "original value"
console.log(proxy.proxied); // "replaced value"

ts

在 js 中, 以 number 与 Number 举例,后者是前者的包装对象

在 ts 中,以 number 与 Number 举例,前者是 ts 中的类型,后者是 js 中的对象

总结:在 ts 中使用小写来定义参数类型(如 age:number)

判断数据类型

字面量:数据固定值,不用构造函数创建

基本类型:不属于引用类型

//基本类型
console.log(typeof 'str');      // 输出 "string"
//引用类型
console.log(String.prototype.isPrototypeOf('str'));     // false
console.log('str' instanceof String);                   // false
引用string实例的属性、方法时:字面量string会临时转换为对象
console.log(String.prototype.isPrototypeOf('str'));     // false
console.log('str'.length);                   // 3
console.log('str'.includes('s'));            //true

引用类型:仍然是引用类型

console.log(typeof {});      // 输出 "object"

运算符

typeof:判断 基本数据类型+ 广义函数(function、promise、箭头函数)

typeof null=Object 类型标签均为000
typeof NaN==Number:全局方法isNaN()
// 基本类型的字面量
console.log(typeof undefined);    // 输出 "undefined"
console.log(typeof null);         // 输出 "object"(历史遗留 Bug)
console.log(typeof true);         // 输出 "boolean"
console.log(typeof 42);            // 输出 "number"
console.log(typeof NaN);            // 输出 "number"
console.log(typeof 'string');      // 输出 "string"
console.log(typeof Symbol());      // 输出 "symbol"
console.log(typeof BigInt(42));    // 输出 "bigint"
// 特殊引用类型 function
console.log(typeof function(){});  // 输出 "function",匿名函数
console.log(typeof (() => {}).prototype); // 输出 "function",但并非function实例对象
console.log(typeof Promise);      // 输出 "function",异步函数设计
console.log(Function.prototype.isPrototypeOf(new Promise(()=>{})));     // false
// 引用类型
console.log(typeof {});            // 输出 "object"
console.log(typeof []);            // 输出 "object"
console.log(typeof new Date());    // 输出 "object"
console.log(typeof /regex/);       // 输出 "object"
console.log(typeof new Map());     // 输出 "object"
console.log(typeof new Set());     // 输出 "object"
console.log(typeof new WeakMap()); // 输出 "object"
console.log(typeof new WeakSet()); // 输出 "object"

实例 instanceof 构造函数:判断原型链

Object.prototype.isPrototypeOf({})// true
{} instanceof Object// true

方法

构造函数.prototype.isPrototypeOf(实例) :判断原型链

(数据).constructor === 数据类型:不包含继承类型

​(1).constructor ===Number//true

//​()转换为Number

显示

toString,valueOf

除了null,undefined

基本数据类型、function,Array,RegExp:返回数据本身

//基本数据类型
//ES5:Null,Undefined,Number,String,Boolean
//ES6:Symbol
//ES10:Bigint
console.log(Symbol('foo').toString());//"Symbol(foo)"
console.log(Symbol('foo').valueOf());//Symbol(foo)

引用数据类型

Object,(Weak)Map、(Weak)Set:[object 类型]

Date:...中国标准时间(ECMAScript规范定义的日期时间字符串格式)

valueOf:this 值转换为对象

在这里插入图片描述

let set=new Set()
set.add(1)
console.log(set.toString()); //"[object Set]"
console.log(set.valueOf()); //[object Set]

let mp=new Map()
mp.set("1",1)
console.log(mp.toString()); //"[object Map]"
console.log(mp.valueOf()); //[object Map]

toString:重写对象的类型转换

在这里插入图片描述在这里插入图片描述

//"Sun Dec 17 1995 03:24:00 GMT+0800 (中国标准时间)"
console.log(new Date("December 17, 1995 03:24:00").toString()); 

类型转换

Number

数字字面量:浮点数值

像 37 这样的数字字面量是浮点数值,而不是整数。JavaScript 没有单独的整数类型。

显式类型转换

Number(任意类型):任意类型->string、若string含非数字,会返回NaN
[num]为num
undefined、{} 为 NaN
null 、[]、''空字符串或仅包含空格的字符串、为 0
console.log(Number({}))//NaN
console.log(Number([]))//0
console.log(Number([1]))//1
console.log(Number(null))//0
console.log(Number(undefined))//NaN
BigInt 抛出 TypeError,以防止意外的强制隐式转换导致精度损失
Symbol 抛出 TypeError  
Date:秒
Number(new Date("December 17, 1995 03:24:00"));//819199440000
前导和尾随的空格/换行符会被忽略
前导的数字 0 不会导致该数值成为八进制字面量
Number("0x11"); // 17
Number("0b11"); // 3
Number("0o11"); // 9
+ 和 - 是独立的一元运算符,后面不能跟空格

不允许使用数字分隔符 

parseInt(string[,radix]):基数radix是2-36之间的整数
parseFloat(string):解析一个参数并返回一个浮点数,无法识别 0x 前缀
区别:pase类自动截断尾部非数字,Number不会截断
console.log(parseInt('6f'));//6
console.log(parseFloat('6f'));//NaN
console.log(Number('6f'));//6
parseInt(string[,radix]):基数radix是2-36之间的整数
parseFloat(string):解析一个参数并返回一个浮点数

隐式转换:+str-,含boolean的相加

str = '123'

  1. str - 1 //122
  2. +str+1 // 124
  3. str+1 // '1231'

String

显式类型转换

除了null/undefined.toString()  
String(任意类型) 

隐式转换:含str的相加

+''

Boolean

显式类型转换

Boolean():0, ''(空字符串), null, undefined, NaN会转成false,其它都是true

隐式转换 :!!

比较

字符串:字符顺序(等长),长的大(短是长的前缀)

console.log('apple' < 'banana'); // true,因为 'a' 在 Unicode 中比 'b' 小
console.log('apple' < 'apples'); // true,因为 'apple' 是 'apples' 的前缀
console.log('apple' < 'apricot'); // true,因为 'l' 在 Unicode 中比 'r' 小

相加减:交换顺序后结果不变

num相加

console.log(Number([1]))//1
console.log(Number([]))//0
console.log(Number(null))//0
console.log(Number({}))//NaN
console.log(Number(undefined))//NaN

null、undefined、boolean基本类型:转Number

console.log(1+null); //1
console.log(undefined+1); //NaN

obj、function、arr、Date等引用类型:转string

console.log({}+1)//[object Object]1
console.log(1+{a:1,b:2})//1[object Object]
console.log(typeof(1+{a:1}))//string
console.log(1+function(){console.log()}); "1function(){console.log()}"
因为只有[]\[num]这两类特殊的数字才能转换为Number、所以为了统一,arr:转string优先于Number
console.log([]+1); // "1"
console.log(1+[]); // "1"
console.log(1+['a'])//1a 
console.log(1+['a',2])//1a,2
console.log(1+[2,2])//12,2
console.log([0,1]+[2,2])//0,12,2

num相减:能转number就转,不能则NaN

//number与其他数据相加减
//:能转number就转,不能则转string相加,object,arr(元素超过1个 或者 非number元素)
console.log(1-{})//NaN
console.log(1-[])//1
console.log(1-[1])//0
console.log(1-['a'])//NaN
console.log(1-null)//1

相等

全局属性 NaN :非数字的值,它与任何其他值(包括自身)都不相等

isNaN(string/Number/boolean/null)

Object.is(val0, val1):NaN等,±0不等

只能比较字面量,对象只会判为false
const obj = {};
console.log(Object.is(obj, {}));
// Expected output: false

===、==:NaN不等、±0等

Object.is() 使用了 "SameValueZero" 比较算法,它不会对 NaN 进行特殊处理,而是按照严格的值相等性规则比较

console.log(NaN===NaN);
// Expected output: false

console.log(NaN==NaN);
// Expected output: false

console.log(Object.is(NaN, NaN));
// Expected output: true

console.log(Object.is(-0, +0));
// Expected output: false

console.log(Object.is(null, undefined));
// Expected output: false

松散相等==(可自动转换类型) 和 严格相等===

比较的是内存单元的内容

255 === 255.0; // true
255 === 0xff; // true(十六进制表示)
255 === 0b11111111; // true(二进制表示)
255 === 0.255e3; // true(十进制指数记数法)

对象传递是引用地址:判断对象相等,需要深度比较

const obj = {};
console.log(Object.is(obj, {}));
// Expected output: false
set用===判断是否相等
//Set用===判断是否相等
const set= new Set();
const obj1={ x: 10, y: 20 },obj2={ x: 10, y: 20 }
set.add(obj1).add(obj2);

console.log(obj1===obj2);//false
console.log(set.size);// 2

set.add(obj1);
console.log(obj1===obj1);//true
console.log(set.size);//2

对象判空

JSON.stringify(obj) == '{}'

Object.keys(obj).length==0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值