首页 > PHP资讯 > HTML5培训技术 > js类型判断及鸭式辨型

js类型判断及鸭式辨型

HTML5培训技术
三种检测对象的类方式: 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
        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
 
本文由欣才IT学院整理发布,未经许可,禁止转载。