基本数据类型的值是按值访问的
一种既非对象也无方法的数据,所有基本类型的值都是不可改变的。但需要注意的是,基本类型本身和一个赋值为基本类型的变量的区别。变量会被赋予一个新值,而原值不能像数组、对象以及函数那样被改变。
typeof instance === "undefined"typeof instance === "boolean"typeof instance === "number"typeof instance === "string"typeof instance === "bigint"Symbol() 创建,这个函数动态地生成了一个匿名,唯一的值。Symbol类型唯一合理的用法是用变量存储 symbol的值,然后使用存储的值创建对象属性。typeof instance === "symbol"
var myPrivateMethod = Symbol();
this[myPrivateMethod] = function() {...};
引用类型的值是按引用访问的。查看所有的标准内置对象。
除过上面的 7 种基本数据类型外,剩下的就是引用类型了,统称为 Object 类型。细分的话,有:Object 类型、Array 类型、Date 类型、RegExp 类型、Function 类型 等。typeof instance === "object"。
记住 typeof 操作符的唯一目的就是检查数据类型,如果我们希望检查任何从 Object 派生出来的结构类型,使用 typeof 是不起作用的,因为总是会得到 “object”。检查 Object 种类的合适方式是使用 instanceof 关键字。但即使这样也存在误差。详情看下面的”判断类型的方法“小节
经常用来检测一个变量是不是最基本的数据类型,适合用于比较简单的场景,如特定类型判断,是否是字符串、是否是函数等
var a;
typeof a; // undefined
a = null;
typeof a; // object
a = true;
typeof a; // boolean
a = 666;
typeof a; // number
a = "hello";
typeof a; // string
a = Symbol();
typeof a; // symbol
a = function(){}
typeof a; // function
a = [];
typeof a; // object
a = {};
typeof a; // object
a = /aaa/g;
typeof a; // object
优点:
局限性:
这是浏览器的BUG:所有的值在计算中都以二进制编码储存,浏览器中把前三位000的当作对象,而null的二进制前三位是000,所以被识别为对象,但是他不是对象,他是空对象指针,是基本类型值。详细讲解可以看这篇文章: 浅谈 instanceof 和 typeof 的实现原理
用来判断某个构造函数的 prototype 属性所指向的对象是否存在于另外一个要检测对象的原型链上,简单说就是判断一个引用类型的变量具体是不是某种类型的对象(注意:instanceof 后面一定要是对象类型,并且大小写不能错) 适合用于判断【自定义的类】实例对象, 而不是用来判断原生的数据类型
({}) instanceof Object // true
([]) instanceof Array // true
(/aa/g) instanceof RegExp // true
(function(){}) instanceof Function // true
优点:
局限性:
返回一个表示该对象的字符串,适合用于检查【内置类】
使用Object.prototype.toString检查对象类型
Object.prototype.toString 的原理是当调用的时候, 就取值内部的 [[Class]] 属性值, 然后拼接成 ‘[object ‘ + [[Class]] + ‘]’ 这样的字符串并返回. 然后我们使用 call 方法来获取任何值的数据类型.
Object.prototype.toString.call("123") // [object String]
Object.prototype.toString.call(123) // [object Number]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call([1,2,3]); // [object Array]
Object.prototype.toString.call(function () {}); // [object Function]
Object.prototype.toString.call(Math); // [object Math]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call(/\d/); // [object RegExp]
Object.prototype.toString.call(Symbol); // [object Symbol]
优点:
局限性:
此方法是基于JS本身专门进行数据检测的,所以是目前检测数据类型比较好的方法。
function _typeof(obj){
var s = Object.prototype.toString.call(obj);
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
// or
function type(obj) {
return typeof obj !== "object" ? typeof obj : Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}
/**
* @desc 是否是 Undefined 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isUndefined(obj) {
return obj === void 0;
}
/**
* @desc 是否是 Null 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isNull(obj) {
return obj === null;
}
/**
* @desc 是否是 Boolean 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isBoolean(obj) {
return typeof(obj) === 'boolean';
}
/**
* @desc 是否是 Number 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isNumber(obj) {
return typeof(obj) === 'number';
}
/**
* @desc 是否是 String 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isString(obj) {
return typeof(obj) === 'string';
}
/**
* @desc 是否是 Object 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
/**
* @desc 是否是 Array 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isArray(obj){
return Array.isArray?Array.isArray(obj):Object.prototype.toString.call(obj) === '[object Array]';
}
/**
* @desc 是否是 Function 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isFunction(obj){
return typeof(obj) === 'function';
}
/**
* @desc 是否是 Date 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isDate(obj){
return Object.prototype.toString.call(obj) === '[object Date]';
}
/**
* @desc 是否是 RegExp 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isRegExp(obj){
return Object.prototype.toString.call(obj) === '[object RegExp]';
}
/**
* @desc 是否是 Error 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isError(obj){
return Object.prototype.toString.call(obj) === '[object Error]';
}
/**
* @desc 是否是 Arguments 类型检测
* @param obj 待检测的数据
* @return {Boolean} 布尔值
*/
function isArguments(obj){
return Object.prototype.toString.call(obj) === '[object Arguments]';
}
JavaScript 是弱类型语言,而且JavaScript 声明变量的时候并没有预先确定的类型,变量的类型就是其值的类型,也就是说变量当前的类型由其值所决定,夸张点说上一秒种的String,下一秒可能就是个Number类型了,这个过程可能就进行了某些操作发生了强制类型转换。虽然弱类型的这种不需要预先确定类型的特性给我们带来了便利,同时也会给我们带来困扰,为了能充分利用该特性就必须掌握类型转换的原理。
堆和栈的区别 堆是动态分配内存,内存大小不一,也不会自动释放。栈是自动分配相对固定大小的内存空间,并由系统自动释放。
javascript的基本类型就5种:Undefined、Null、Boolean、Number和String,它们都是直接按值存储在栈中的,每种类型的数据占用的内存空间的大小是确定的,并由系统自动分配和自动释放。这样带来的好处就是,内存可以及时得到回收,相对于堆来说,更加容易管理内存空间。
javascript中其他类型的数据被称为引用类型的数据 : 如对象(Object)、数组(Array)、函数(Function) …,它们是通过拷贝和new出来的,这样的数据存储于堆中。其实,说存储于堆中,也不太准确,因为,引用类型的数据的地址指针是存储于栈中的,当我们想要访问引用类型的值的时候,需要先从栈中获得对象的地址指针,然后,在通过地址指针找到堆中的所需要的数据。
toString()是Object的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。
JavaScript 万物皆对象,为什么 xxx.toString() 不能返回变量类型?
这是因为 各个类中重写了toString的方法,因此需要调用Object中的toString方法,必须使用toString.call()的方式调用。
对于 Object 对象,直接调用toString()就能返回'[object Object]' 。而对于其他对象,则需要通过call / apply来调用才能返回正确的类型信息。
非负整数会最先被列出,排序是从小到大的数字顺序.size()方法即可;而读取 Object 的长度则需要额外的计算: Object.keys(obj).length可迭代对象,所以其中的键值对是可以通过for of循环或.forEach()方法来迭代的;而普通的对象键值对则默认是不可迭代的,只能通过for in循环来访问(或者使用Object.keys(o)、Object.values(o)、Object.entries(o)来取得表示键或值的数字)迭代时的顺序就是上面提到的顺序。 Object.prototype.x = 1;
const o = {x:2};
const m = new Map([[x,2]]);
o.x; // 2,x = 1 被覆盖了
m.x; // 1,x = 1 不会被覆盖
.toJSON()方法,然后在JSON.parse()中传入复原函数来将其复原虽然 Map 在很多情况下会比 Object 更为高效,不过 Object 永远是 JS 中最基本的引用类型,它的作用也不仅仅是为了储存键值对。
//toString的对象
var obj2 = {
toString:function(){
return 'a'
}
}
console.log('2'+obj2)
//输出结果2a
//常规对象
var obj1 = {
a:1,
b:2
}
console.log('2'+obj1);
//输出结果 2[object Object]
//几种特殊对象
'2' + {} // "2[object Object]"
'2' + [] // "2"
'2' + function (){} // "2function (){}"
'2' + ['koala',1] // 2koala,1