JavaScript范例推断

JS(ES6)中的基本数据范例:1.数值型(Number):包含整数、浮点数、2.布尔型(Boolean)、3.字符串型(String)、4.数组(Array)、5.空值(Null) 、6.未定义(Undefined),基本数据范例是按值接见的,因为能够直接操纵保存在变量中的现实值。

援用范例:Object 、Array 、Function 、Data,援用数据范例是保存在堆内存中的对象

1.typeof

var a;
console.log("1:" + typeof a);
var b = null;
console.log("2:" + typeof b);
var c = undefined;
console.log("3:" + typeof c);
var d = new Object;
console.log("4:" + typeof d);
var e = function() {};
console.log("5:" + typeof e);
var f = {};
console.log("6:" + typeof f);
var g = '';
console.log("7:" + typeof g);
var h = [];
console.log("8:" + typeof h);
var i = true;
console.log("9:" + typeof i);
var j = 123;
console.log("10:" + typeof j);
var k = NaN;
console.log("11:" + typeof k);
var l = /^[-+]?\d+$/;
console.log("12:" + typeof l);

打印效果以下
《JavaScript范例推断》

总结:typeof对null、undefined、NaN、数组、正则、Object的范例都为object

2.constructor

constructor 用于推断一个变量的原型,constructor 属性返回对建立此对象的数组函数的援用.

当一个函数 F被定义时,JS引擎会为F增加 prototype 原型,然后再在 prototype上增加一个 constructor 属性,并让其指向 F 的援用,当实行 var f = new F() 时,F 被当成了组织函数,f 是F的实例对象,此时 F 原型上的 constructor 通报到了 f 上,因而 f.constructor === F

var F = function(){}
console.log(F.prototype);
var f = new F();
console.log(f.constructor===F) //true

不难看出,F 应用原型对象上的 constructor 援用了本身,当 F 作为组织函数来建立对象时,原型上的 constructor 就被遗传到了新建立的对象上, 从原型链角度讲,组织函数 F 就是新对象的范例。如许做的意义是,让新对象在降生今后,就具有可追溯的数据范例,也就是说对象的constructor属性指向他的组织函数

所以内置对象在内部构建时阔以如许做出推断

《JavaScript范例推断》

  • null 和 undefined 是无效的对象,因而是不会有 constructor 存在的,这两种范例的数据须要经由过程其他体式格局来推断
  • constructor属性并不是肯定指向组织函数,他也是能够修正、变动的(当把F.prototype = {}改写后,会默许把constructor覆蓋掉)

instanceof

instanceof 运算符用来测试一个对象在其原型链中是不是存在一个组织函数的 prototype 属性

及的组织函数有这些基本范例:String、Number、Boolean、Undefined、Null、Symbol(ES6引入了一种新的原始数据范例Symbol,示意举世无双的值);
庞杂范例:Array,Object;
其他范例:Function、RegExp、Date。
var obj = new Object()
obj instanceof Object // true

注重左边必需是对象(object),假如不是,直接返回false,列如:

var num = 1
num instanceof Number // false

num = new Number(1)
num instanceof Number // true

能够看出都是num,而且都是1,只是因为第一个不是对象,是基本范例,所以直接返回false,而第二个是封装成对象,所以true。
这里要严厉注重这个题目,有些说法是检测目的的__proto__与组织函数的prototype雷同即返回true,这是不严谨的,检测的肯定如果对象才行,如:

基本范例

var num = 1
num.__proto__ === Number.prototype // true
num instanceof Number // false

num = new Number(1)
num.__proto__ === Number.prototype // true
num instanceof Number // true
num.__proto__ === (new Number(1)).__proto__ // true

上面例子能够看出,1与new Number(1)几乎是一样的,只是区分在于是不是封装成对象,所以instanceof的效果是差别的,string、boolean等,这些基本范例一样的。

new String(1) // String {"1"}
String(1) // "1"

new String(1)与String(1)是差别的,new是封装成对象,而没有new的只是基本范例转换,照样基本范例
其他基本范例一样的。

庞杂范例,比方数组与对象,以至函数等,与基本范例差别。

庞杂范例

var arr = []
arr instanceof Array // true
arr instanceof Object // true
Array.isArray(arr) // true

庞杂范例从字面量是直接天生组织函数的,所以不会像基本范例一样两种状况。
然则上面那个题目,固然,基本范例也会有这个题目,就是与Object对照。没办法,Object在原型链的上层,所以都邑返回true,以下:

(new Number(1)) instanceof Object // true

因为从下往上,比方你推断是Number,那就没必要推断是不是是Object了,因为已经是Number了……

其他范例

var reg = new RegExp(//)
reg instanceof RegExp // true
reg instanceof Object // true

var date = new Date()
date instanceof Date // true
date instanceof Object // true

除了Function,都一样,详细Function以下:

function A() {}
var a = new A()
a instanceof Function // false
a instanceof Object // true
A instanceof Function // true

这里要注重,function A() {}相当于var A; A = function() {},然后剖析:

  1. a是new出来,所以是经由组织,因而已经是对象,不再是函数,所以false
  2. a是经由组织的对象,返回ture没题目
  3. A是个函数,这没什么题目

{}.toString.call(obj)

用法以下

console.log({}.toString.call(1));
console.log({}.toString.call("11"));
console.log({}.toString.call(/123/));
console.log({}.toString.call({}));
console.log({}.toString.call(function() {}));
console.log({}.toString.call([]));
console.log({}.toString.call(true));
console.log({}.toString.call(new Date()));
console.log({}.toString.call(new Error()));
console.log({}.toString.call(null));
console.log({}.toString.call(undefined));
console.log(String(null));
console.log(String(undefined));

返回以下

《JavaScript范例推断》

注重:必需经由过程 call 或 apply 来挪用,而不能直接挪用 toString , 从原型链的角度讲,一切对象的原型链终究都指向了 Object, 根据JS变量查找划定规矩,其他对象应当也能够直接接见到 Object 的 toString要领,而事实上,大部分的对象都完成了本身的 toString 要领,如许就可能会致使 Object 的 toString 被停止查找,因而要用 call/apply 来强迫挪用Object 的 toString 要领

jQuery中的要领$.type(),就是用到了toString

type: function( obj ) {
    if ( obj == null ) {
        return obj + "";
    }
    // Support: Android<4.0, iOS<6 (functionish RegExp)
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ toString.call(obj) ] || "object" :
        typeof obj;
},

剖析源代码:

typeof obj === "object" || typeof obj === "function" ? class2type[ toString.call(obj) ]

经由过程推断传入范例,假如是object或许function范例就直接返回class2type 中键值是对的效果,假如不是,那末肯定就是基本范例, 经由过程 typeof 就能够

class2type[ toString.call(obj) ] || "object"

这是为了防备一些未知状况的,假如未取到,就返回object,保证了顺序可用性

参考文章:
JS范例推断,typeof/constructor/instanceof的区分
js中的constructor和prototype
JS范例推断
jquery源码
揭开js之constructor属性的神奇面纱

    原文作者:羊先生
    原文地址: https://segmentfault.com/a/1190000017756783
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞