0 / JS中创建值的两种方式
JS 中创建一个值有两种方案:① 字面量方式 ② 构造函数方式
注意:构造函数方式
① 不能 new Symbol/new BigInt
② 可以Object(symbol)/Object(bigint)
其他数据类型值也可以,但是排除null/undefined
//=> 字面量方式
let n = 100;
let obj = {};
//=> 构造函数方式
let m = new Number(100);
let obj2 = new Object();
△ 创建值的两种方式
对于基本数据类型,两种创建方式结果是不一样的:
① 字面量方式得到的是基本数据类型,即:特殊的实例
② 而构造函数方式得到的是对象数据类型,即:正规的实例
对于引用数据类型,两种创建方式结果:除了语法上的区别,本质上是没有区别的,获取的都是对应类的实例对象
1 / JS中数据类型检测
JS中数据类型检测:
① typeof value;
简单方便
② Object.prototype.toString.call(value)
万全之策
③ prop instanceof constructor
临时当“壮丁”
④ constructor
临时当“壮丁”
2 / typeof
△ 图1_typeof 判断数据类型
typeof 检测数据类型:
1、 可以有效的检测出大部分的数据类型
2、 typeof null
检测的结果是object
JS设计的如此:数据值都是按照二进制存储的1整数,010浮点数,100字符串,110布尔,000对象,-2^30undefined,000000null…………
即:typeof 检测数据类型时,按照二进制存储的值检测的,把null认为是对象了
3、 typeof 不会细分具体的对象数据类型值,所有的对象数据类型值,检测出来都是"object"
4、 typeof 检测基于构造函数创建出来的,基本数据类型的实例对象,结果也是"object"
△ 图2_基于构造函数创建出来的基本数据类型的实例对象
3 / Object.prototype.toString.call()
Object.prototype.toString.call() 检测每个对象的类型
1、大部分内置类的原型上都有toString方法,但一般都是转为字符串,只有Object.prototype上的toString方法使用来返回当前实例对象所属的信息
"[object 所属的构造函数信息]"
2、所属的构造函数信息:是根据Symbol.toStringTag
来获取的,【有,是根据它;没有,是浏览器自己计算的】
var toString = Object.prototype.toString;
toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
△ Object.prototype.toString
var class2type = {};
var toString = class2type.toString;
toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
△ ({}).toString
function* fn() {}
console.log(Object.prototype.toString.call(fn)); //->"[object GeneratorFunction]"
△ 构造器函数
function Fn() {}
Fn.prototype[Symbol.toStringTag] = 'Miao~';
let f = new Fn;
console.log(Object.prototype.toString.call(f)); //=>"[object Miao~]"
△ 自定义类,指定toStringTag的值
4 / instanceof
instanceof 运算符检测构造函数的prototype属性是否出现在某个实例对象的原型链上
∴ 基于instanceof可以细分不同类型的对象,也可以检测基于构造函数方式创建的基本数据类型对象的值
但是,临时拉来当“壮丁”,有一些注意事项:
1、检测原理:构造函数[Symbol.hasInstance](实例)
2、检测原理:检测当前构造函数的原型prototype是否出现在当前实例所处的原型链上\__proto__,即:只要能出现结果就为true
3、在JS中原型链是可以手动改的,检测结果不准确
4、所有的实例的原型链最后都指向了Object.prototype
,即:实例 instanceof Object
结果都会为true
5、字面量方式创建的基本数据类型值是无法基于instanceof检测的(浏览器不会把它转为new的方式),即:字面量创建的基本数据类型值不是对象,不存在\__proto__这个东西
6、…………
var n = 100;
var m = new Number(1000);
console.log(n instanceof Number); //=> false
console.log(m instanceof Number); //=> true
console.log(m instanceof Object); //=> true
var arr = [1,2,3];
var obj = {name:'朝霞的光影笔记', id:'zhaoxiajingjing'};
console.log(arr instanceof Array); //=> true
console.log(obj instanceof Object); //=> true
console.log(arr instanceof Object); //=> true
△ 字面量和构造函数创建值
class Fn {
static[Symbol.hasInstance](){
console.log('miao~');
return false;
}
}
let f = new Fn;
console.log(f instanceof Fn);
//=>输出结果:
// miao~
// false
△ 调用:构造函数的Symbol.hasInstance
function Fn(){}
Fn.prototype = Array.prototype;
let f = new Fn;
console.log(f instanceof Array); //=> true
△ 手动修改原型指向
5 / constructor
constructor构造器,被拉来检测数据类型,也是临时抓来的“壮丁”
它的问题:可以手动被修改掉
var n = 100;
var m = new Number(1000);
console.log(n.constructor === Number); //=> true
console.log(m.constructor === Number); //=> true
var arr = [1,2,3];
var obj = {name:'朝霞的光影笔记', id:'zhaoxiajingjing'};
console.log(arr.constructor=== Array); //=> true
console.log(obj.constructor === Object); //=> true
console.log(arr.constructor === Object); //=> false
△ 通过constructor检测
function Fn(){}
Fn.prototype = {
constructor:Array
};
let f = new Fn;
console.log(f.constructor === Fn); //=> false
console.log(f.constructor === Array); //=> true
△ 可以手动修改constructor指向
6 / 小结
JS中检测数据类型的方式4种:
1、typeof,无法区分对象数据类型值
2、Object.prototype.toString,万全之策,主要检测Symbol.toStringTag的值,没有就按浏览器计算的
3、instanceof,“壮丁”
① 检测原理:构造函数[Symbol.hasInstance]()
② 检测构造函数的prototype原型是否出现在实例对象的原型链上
=> JS的原型链是可以手动修改指向的
=> JS的原型也是可以手动修改的
③ 不能检测字面量创建的基本类型值
4、constructor,“壮丁” 可以进行手动修改指向
- end-
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。