zoukankan      html  css  js  c++  java
  • js类型判断及鸭式辨型

     目录

    instanceof

    constructor 

    构造函数名字

    鸭式辨型

    三种检测对象的类方式: instanceof、constructor 、构造函数名字

    用法如下:

    1)instanceof

    console.log([1,2,3] instanceof Array);
    true
    
    console.log([1,2,3] instanceof Object);
    true

    尽管构造函数是原型的唯一标识,instanceof运算符的右操作数是构造函数,instanceof实际计算过程中检测的是对象的继承关系,而不是检测的创建对象时的构造函数,只是使用了构造函数作为中介

    当然也可以使用isPrototypeOf 来判断一个对象是否存在于另一对象的原型链中,此时不使用构造函数作为中介

    var a1 = new Array();
    console.log(Array.prototype.isPrototypeOf(a1));
    true
    
    console.log(Array.prototype.isPrototypeOf([1,2,3]));
    true

    注意:多个执行上下文时(例如存在不同框架时)instanceof使用有限制

    2)constructor

    每个javascript函数都可以用作构造函数,调用构造函数需要使用prototype属性,因而每个javascript函数会自动拥有prototype属性,这个属性值是一个对象,这个对象包含一个contructor属性,constructor属性值是一个函数对象。

    即对于函数var F = function(){}; F.prototype.constructor===F

    关系图如下:

     

    eg:

    var F= function(){};
    var p = F.prototype;
    var c = p.constructor;
    console.log(p);
    console.log(c);
    console.log(c===F);
    Object {}
    function (){} true

    因而对象继承的constructor均指代他们的构造函数

    eg:

    var o= new F();
    console.log(o.constructor===F);

    //输出 
    true
    var a = new Array();
    console.log(a.constructor===Array);
    //输出
    true
    function typeDiscern(x){
      switch(x.constructor){
        case Number: return "Number:"+x;
        case String: return "String:"+x;
        case Array: return "Array:"+x;
            }
    }
    console.log(typeDiscern([1,2,3]));
    console.log(typeDiscern("abc"));
    console.log(typeDiscern(5));
    //输出
    Array:1,2,3
    String:abc
    Number:5

    注意: 同instanceof在多个上下文下没法使用,另外并不是所有的对象都包含constructor属性

    eg:

    定义Person类

    function Person(name)   
    {   
       this.name=name;   
       this.getName=function()   
            {   
               return this.name;   
            }   
    };   
      
    var wish=new Person('js');   
      
    console.log(wish.constructor==Person); 
    console.log(Person.prototype);
    console.log(Person.constructor);  
    console.log(wish.getName());

    //输出
    true Person {} function Function() { [native code] } js

    给Person自定义prototype

    function Person(name)   
    {   
       this.name=name;   
       this.getName=function()   
            {   
               return this.name;   
            }   
    };   
    Person.prototype={
        toString: function(){
            return this.name;
        }
    };
      
    var wish=new Person('js');   
      
    console.log(wish.constructor==Person); 
    console.log(Person.prototype);
    console.log(Person.constructor);  
    console.log(wish.getName());
    console.log(wish.toString());

    //输出
    false Object {toString: function} function Function() { [native code] } js js

    此时新定义的原型对象不含有constructor属性,因而Person的实例也不包含constructor属性

    解决方法:可显示的给原型添加构造方法

    Person.prototype={
        constructor=Person,
        toString: function(){
            return this.name;
        }
    };

     构造函数名字

    没有intanceof和constructor的执行上下文问题,一个窗口中的Array构造函数和另一个窗口内Array构造函数不等,但是构造函数名字相同,但是并不是每个函数都有名字

    Function.prototype.getName= function(){
        if("name" in this){
            return this.name;
        }
        return this.name=this.toString().match(/functions*([^(]*)/);
    }
    function test1(){
    }
    console.log(test1.getName());

    //输出: test1

    鸭式辨型

    关注对象能做什么,而不是对象的类是什么

    James Whitcomb Riley提出像鸭子一样走路、游泳和嘎嘎叫的鸟就是鸭子

    主要对象包含walk(),swim(),bike()这三个方法就可以作为参数传入

    利用鸭式辩型实现的函数:

    function quackImplements(o/*,...*/){
        for(var i=1; i<arguments.length;i++){
            var arg=arguments[i];
            switch(typeof arg){
                case 'string':
                    if(typeof o[arg]!=="function")
                        return false;
                    continue;
    
                case 'function':
                    arg=arg.prototype;
    
                case 'object':
                    for (var m in arg){
                        if(typeof arg[m]!=="function") continue;
                        if(typeof o[m]!=="function") return false;
    
                }
            }
        }
        return true;
    }

    对于字符串直接检查命名方法

    对于对象检查是否有同名方法

    对于函数检查构造函数的原型对象中是否有相同方法

    在javascript中很多函数都不对对象做类型检测只是关心这些对象能做什么

    eg:Array的prototype利用了鸭式辨型,arguments是伪数组

     (function () {
         var arr = Array.prototype.slice.apply(arguments);
            console.log(arr);
    })(1, 2, 3);

    //输出: [
    1, 2, 3]
     var arr = Array.prototype.slice.apply({ 0: 1, 1: 2, 2: 3, length: 3 });
     console.log(arr);
    
    //输出:
    [1, 2, 3]

    使用鸭式辨型可以扩大对象的使用范围

    eg:让普通对象具有数组的push方法

    Function.prototype.unCurrying = function () {
        var f = this;
        return function () {
            var a = arguments;
            return f.apply(a[0], [].slice.call(a, 1));
        };
    };
    Function.prototype.unCurrying = function () {
        return this.call.bind(this);
    };
    
    var push = Array.prototype.push.unCurrying(),
    obj = {};
    push(obj, 'first', 'two');
    console.log(obj);
    console.log("length:"+obj.length)

    输出:

    Object{0: "first", 1: "two", length: 2}
    length:2

    参考:javascript权威指南

        http://www.cnblogs.com/pigtail/p/3450852.html

  • 相关阅读:
    mybatis异常:org.apache.ibatis.builder.IncompleteElementException: Could not find parameter map com.sunyan.domain.User
    Markdown首行缩进和换行
    mybatis入门——mybatis的概述
    python2跟python3的区别
    码云与git
    Python入门(一)
    python环境搭建
    python简介
    计算机基础
    Typora、安装及使用
  • 原文地址:https://www.cnblogs.com/wishyouhappy/p/3721778.html
Copyright © 2011-2022 走看看