JavaScript 三种要领,能够肯定一个值究竟是什么范例

JavaScript 三种要领,可以肯定一个值究竟是什么范例。

typeof

instanceof

Object.prototype.toString

为何须要肯定范例 ?

​ 只要肯定范例的状况,才晓得当前操纵对象具有哪些功用; 比方运用 push,unshfit,shfit 等要领时,那末其必需为数组范例时才准确运用;

​ 当某些状况增加范例搜检时,如许代码越发硬朗,平安;

typeof 运算符

返回一个值的数据范例。

基础语法:

typeof operand
or
typeof (operand)

operand 是一个表达式,示意对象或原始值,其范例将被返回。括号是可选的.

示例:基础数据范例

{

    typeof 1            // "number"
    typeof Number(1)    // "number"
    typeof ''           // "string"
    typeof true         // "boolean"
    typeof null         // "object"
    typeof undefined    // "undefined"
    typeof Symbol       // "function"

}

当操纵数(operand)为基础数据范例,其返回字符串与希冀一样,也可以分辨当前操纵数得范例;

这里须要说起下基础数据范例 null ,为何 typeof null 返回的字符串为 “object”;

在 JavaScript 最初的完成中,JavaScript 中的值是由一个示意范例的标签和现实数据值示意的。对象的范例标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因而,null的范例标签也成为了 0,typeof null就毛病的返回了”object"

示例:援用数据范例

    typeof new Number(1)          //  'object'
    typeof new String()         //  'object'
    typeof new Array()          //  'object' 
    typeof new Date()             //  'object'
    
     typeof new Function()       //  'function'

从上面看出,一切经由过程 new 症结实例化的组织函数返回都 object 范例. 固然函数是一个破例;

从上述两个示例可以看出,当typeof 的操纵数为基础数据范例、函数返回字符串可以辨别其数据范例;

那末假如须要辨别援用范例时须要借助 JavaScript中别的一个运算符;

instanceof 运算符

推断实例对象是否是类(组织函数)的实例

instanceof 事情道理基于原型链,也就是说假如在对象的原型链上可以找到组织函数的 prototype 对象,那末该操纵就返回 true;

基础语法:**

    object instanceof constructor

参数

  • object
    要检测的对象.
  • constructor
    某个组织函数

示例一:

let o = new Object();
let bool = new Boolean();
let num = new Number(1);
let str = new String();
let arr = new Array();
// 自定义组织函数
function Person(){} 
function Animal(){} 

let person = new Person();
let animal = new Animal();
person instanceof Person   // true
animal instanceof Animal   // true

o instanceof Object;       // true
bool instanceof Boolean;   // true
num instanceof Number;     // true
str instanceof String;     // true
arr instanceof Array;      // true

如许填补 typeof 在检测援用范例的时的题目;

经由过程下面的示例,考证下 instanceof 事情道理:

{
    function Person(){}
    function Animal(){}

    // 比方自定义定义两个类
    let person = new Person();
    let animal = new Animal();


    console.log(animal instanceof Object);  // =>  true
    console.log(animal instanceof Animal);   // true

    console.log(person instanceof Object); // =>  true
    console.log(person instanceof Person);  // true

    console.log(person instanceof Animal);  // =>  false
    console.log(animal instanceof Person);  // =>  false
}

上面应当跟我们预期的一样, 那末有无经由过程一种方法让

person instanceof Animal  // => true

那末来针对上面作以下调解:

person.__proto__ = Animal.prototype;
console.log(person instanceof Animal) // => true
console.log(person instanceof Person) // => false

严厉意义上来讲, 上述这么改是没有意义;这里只是为了考证 instanceof 怎样事情的;其次申明 person instanceof Person 返回 true, 则并不意味着给表达式永久返回 true, Person.prototypeperson.__proto__ 都是可变的;

instanceof 和多个全局对象(多个frame或多个window之间的交互)

可以定义两个页面测试: parent.html、 child.html

//    parent.html

    <iframe src="child.html" onload="test()">
    </iframe>
    <script>
        function test(){
            var value = window.frames[0].v;
            console.log(value instanceof Array); // false
        }
    </script>
//  child.html
    <script>
        window.name = 'child';
        var v = [];
    </script>

严厉上来讲value 就是数组,但parent页面中打印输出: false ;也就是 parent 页面中 Array.prototype != window.frames[0].Array.prototype ;

重要引发题目是,由于多个窗口意味着多个全局环境,差别的全局环境具有差别的全局对象,从而具有差别的内置范例组织函数.

instanceof 运用 – 检测作用域的平安

function Person(name, age){
    this.name = name;
    this.age = age
}

// 一般状况下
{
    let person = new Person('托尼', 20);
    console.log(person.name,person.age);
}

// 假如在实例化时刻遗忘增加 new 症结字尼? 会涌现什么状况尼?
{
     let person = Person('托尼', 20);
    console.log(person.name, person.age);  // Uncaught TypeError: Cannot read property 'name' of undefined
    
    // Person 被看成一般的要领实行,其次 name ,age 被增加window上
    console.log(name, age); //=> 托尼 20
}

// 怎样防止如许状况,在加 new 症结字或省略时刻都能一般返回实例对象 
{
    function Person(name, age){
        if(this instanceof Person) {
            this.name = name;
            this.age = age
            return this;
        }else {
            return new Person(name, age);
        }
    }
    
    let person = Person('托尼', 20);
    console.log(person.name, person.age);  // 托尼 20
}

Object.prototype.toString 要领

默许状况下(不掩盖 toString 要领前提下),任何一个对象挪用 Object 原生的 toString 要领都邑返回 “[object type]”,个中 type 是对象的范例;
每一个类的内部都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的 type(组织函数名) ;

举个例子吧:

console.log(Object.prototype.toString.call([])); // [object Array]

上述中: Array 对应也就当前对象的 type,一样就是当前对象的组织函数名;

前面在说 instanceof 在多个作用域的状况下,尝试用这类体式格局处理:

  function isArray(arr){
      return Object.prototype.toString.call(arr) === "[object Array]"
  }
  
  console.log(isArray(value)); // true

从输出来看时圆满处理了;

为何这类体式格局是可以咧?这里分辨范例依据 组织函数称号,由于原生数组的组织函数称号与全局作用域无关,因而运用 toString() 就可以保证返回一致的值。

同理别的原生对象检测也能根据这类体式格局来,如 Date,RegExp,Function

function isFunction(value) {
        return Object.prototype.toString.call(value) === "[object Function]"
    }
function isDate(value) {
        return Object.prototype.toString.call(value) === "[object Date]"
    }
function isRegExp(value) {
        return Object.prototype.toString.call(value) === "[object RegExp]"
    }

isDate(new Date()); // true
isRegExp(/\w/);        // true
isFunction(function(){}); //true

上述代码,可以作进一步革新,由于 isFunction、isDate、isRegExp 要领中,实在只要 [object ConstructorName] ConstructorName不一样,可以应用工场函数再润饰一下:

 function generator(type){
        return function(value){
            return Object.prototype.toString.call(value) === "[object "+ type +"]"
        }
    }

 let isFunction = generator('Function')
 let isArray = generator('Array');
 let isDate = generator('Date');
 let isRegExp = generator('RegExp');

isArray([]));    // true
isDate(new Date()); // true
isRegExp(/\w/);        // true
isFunction(function(){}); //true

如许纵然要天生别的原生对象考证函数前面时就简朴多了;

总结:

  • typeof 适用于检测值范例, 特别注意 null 的题目,这也是面试用常常碰到的.
  • instanceof 检测援用范例.
  • toString 填补 instanceof 在跨窗口下对范例检测题目, toString 只适应于原生对象;
    关于用户自定义的对象没法辨别的.
    原文作者:任重道远
    原文地址: https://segmentfault.com/a/1190000017390709
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞