• JavaScript 代码小片段


      1.获取对象 obj 的所有属性(自有属性和继承属性),保存到数组 lst 中

    //获取对象obj的所有属性(自有属性和继承属性),保存到数组lst 中
    var lst = [];
    function getAllAttrs(obj){
        var arr = Object.getOwnPropertyNames(obj);
        for(r in arr){
            lst.push(arr[r]);
        }
        if(obj.__proto__ !== null){
            obj = obj.__proto__;
            getAllAttrs(obj);
        }
    }
    getAllAttrs(obj);
    console.log(lst);

      2.实现一个完整的复数类

    //实现一个完整的复数类: Complex
    
    //定义构造函数
    function Complex(real, imaginary){
        if(isNaN(real) || isNaN(imaginary)) throw TypeError();
        this.r = real;
        this.i = imaginary;
    };
    // 定义非静态方法
    Complex.prototype.add = function(that){
        return new Complex(this.r+that.r,this.i+that.i);
    };
    Complex.prototype.mui = function(that){
        return new Complex(this.r*that.r-this.i*that.i,this.r*that.r+this.i*that.i);
    };
        //取模运算
    Complex.prototype.mag = function(){
        return Math.sqrt(this.r*this.r+this.i*this.i);
    };
    Complex.prototype.neg = function(){
        return new Complex(-this.r,-this.i);
    };
    Complex.prototype.toString = function(){
        return "{"+this.r+", "+this.i+"}";
    };
    Complex.prototype.equals = function(that){
        return that != null &&
            that.constructor === Complex &&
            this.r === that.r && 
            this.i === that.i;
    };
    //定义类静态属性
    Complex.ZERO = new Complex(0,0);
    Complex.ONE = new Complex(1,0);
    Complex.I = new Complex(0,1);
    //定义类静态方法
    Complex.parse = function(s){
        try{
            var m = Complex._format.exec(s);
            return new Complex(parseFloat(m[1]),parseFloat(m[2]));
        }catch(x){
            throw new TypeError("Can't parse "+s+" as a complex number.");
        }
    };
    //静态类属性
    Complex._format = /^{([^,]+),([^}]+)}$/;
    
    //使用
    var c = new Complex(2,3);
    var d = new Complex(c.i,c.r);
    console.log(c.add(d).toString()); // {5, 5}
    console.log(Complex.parse(c.toString())); // Complex {r: 2, i: 3}
    console.log(Complex.parse(c.toString()).add(c.neg()).equals(Complex.ZERO)); // true
    

      3.判断鸭辩型

    //判断鸭辩型
    //如果 o 实现了除第一个参数之外的参数所表示的同名方法, 则返回true
    function quacks3(o){
        for(var i=1;i<arguments.length;++i){//遍历o之后的所有参数
            var arg = arguments[i];
            switch(typeof arg){
            case 'string': // 参数为string直接用名字检查
                if(typeof o[arg] !== "function")
                    return false;
                continue;
            case 'function': // 参数为函数, 视为构造函数, 检查函数的原型对象上的方法
                arg = arg.prototype; //进入下一个case
            case 'object':
                for(var m in arg){ //遍历对象的每个属性
                    if(typeof arg[m] !== 'function') //跳过不是方法的属性
                        continue;
                    if(typeof o[m] !== 'function')
                        return false;
                }
                
            }
        }
        return true;
    }
    //说明: 只检测函数名,而不用管细节, 不是强制的API,因此满足鸭辩型的本质, 灵活
    //限制: 不能用于内置类, 因为for/in不能遍历不可枚举的方法. 在ES5中可以使用Object.getOwnPropertyNames()
    function quacks5(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':
                var props = Object.getOwnPropertyNames(arg.__proto__);
                var props2 = Object.getOwnPropertyNames(arg);
                for(var prop in props2){
                    props.push(props2[prop]);
                }
                for(var m in props){
                    if(props[m] !== 'function')
                        continue;
                    if(o[m] !== 'function')
                        return false;
                }
            }
        }
        return true;
    };
    

      4.合并多个对象属性

    // 将变长参数sources对象的可枚举(for/in)属性合并到target中,并返回target
    // target 的值是被修改的, 深拷贝(递归合并)
    // 合并从左到右进行, 同名属性保持和左边一样(除非属性是空对象)
    function myextend(target /*...sources*/){
        if(!arguments.length)
            return undefined;
        if(arguments.length === 1)
            return target;
        for(var i=1;i<arguments.length;++i){
            var source = arguments[i];
            for(var prop in source){
                if(target.hasOwnProperty(prop) &&
                   target[prop] !== undefined && 
                   target[prop] != {}) // 目标对象上该属性存在且属性值不为undefined(可以为null)且不为空对象
                    continue;
                if(typeof source[prop] === 'object'){
                    target[prop] = {};
                    target[prop] = myextend({},source[prop]);
                }else{
                    target[prop] = source[prop];
                }
            }
        }
        return target;
    }
    

    测试:

    // 结果在chrome console中查看
    var target = {
        t1:1,
        t2:{
            t1:1,
            t2:{
                t1:1,
                t2:"t2"
            }
        }
    };
    var source1 = {
        s1:2,
        s2:{
            s1:2,
            s2:{
                s1:2,
                s2:"s2"
            }
        }
    };
    var source2 = {
        r1:3,
        r2:{
            r1:3,
            s2:{
                r1:3,
                r2:"s2"
            }
        }
    };
    var t = myextend(target,source1,source2);
    console.log(t);
    

      5.为对象添加一个id属性

    (function(){
    	Object.defineProperty(Object.prototype,"objectId",{
    		get: idGetter,
    		enumerable: false,
    		configurable: false
    	});
    	function idGetter(){
    		if(!(idprop in this)){
    			if(!Object.isExtensible(this))
    				throw Error("Can't define id for nonextensible objects");
    			Object.defineProperty(this,idprop,{
    				value: nextid++,
    				writable: false,
    				enumerable: false,
    				configurable: false
    			});
    			return this[idprop];
    		}
    	}
    	var idprop = "|***objectId*|";
    	var nextid = 1;
    })();
    
    var obj = {};
    console.log(obj.objectId); // 1
    

      6.让函数既可以当成构造函数,也可以当成工厂方法调用

    // 既可以当成构造函数用, 也可以当成工厂方法来用
    function Range(from, to){
    	var props = {
    		from:{value:from,enumerable:true,writable:false,configurable:false},
    		to:{value:to,enumerable:true,writable:false,configurable:false}
    	};
    	if(this instanceof Range){ // 如果作为构造函数来调用的话
    		Object.defineProperties(this,props);
    	}else{ // 否则当成作为工厂方法来调用
    		return Object.create(Range.prototype,props);
    	}
    }
    

     持续更新中...

     参考

    1. <<JavaScript权威指南: 第6版>>

  • 相关阅读:
    [转][Linux/Ubuntu] vi/vim 使用方法讲解
    [转]在Windows中安装Memcached
    memcached可视化客户端工具
    [转]C#操作Memcached帮助类
    [转]Redis和Memcache区别,优缺点对比
    [转]【转】大型高性能ASP.NET系统架构设计
    [转]浅谈命令查询职责分离(CQRS)模式
    element-UI——el-table添加序号
    xss攻击(转)
    vuex原理
  • 原文地址:https://www.cnblogs.com/roger9567/p/5058411.html
Copyright © 2020-2023  润新知