js中有关类、对象的增强函数
javascript中继承的实现
基础实现
function Range(from,to){
    this.from =from;
    this.to =to;
}
Range.prototype = {
    includes:function(x){
        return this.from<=x &&this.to >=x;
    },
    foreach:function(f){
        for(var x = Math.ceil(this.from);x<=this.to;x++){
            f(x);
        }
    },
    toString:function(){
        return "("+this.from+"..."+this.to+")";
    }
}
var r= new Range(1,3);
console.log(r.includes(2));
// 可以借鉴下面这种用法
r.foreach(alert); // 弹出三次
console.log(r.toString());
寄生组合继承
function SuperType() {
    this.property = true;
}
SuperType.prototype.superMethod = function () {
}
function LowType() {
    SuperType.call(this);
    this.lowProperty = true;
}
function inheritPrototype(subType, superType) {
    var prototype1 = object(superType.prototype);
    prototype1.constructor = subType;
    subType.prototype = prototype1;
}
inheritPrototype(LowType, SuperType);
LowType.prototype.lowMethod = function () {
};
var lowType = new LowType();
线上链接。线上链接主要讲最后一个例子,寄生组合继承,其实这里命名,在我后来都没遇到
还有,如果实例对应的类原型的引用变化了,这个实例指向的原型会变吗?不会的。
最优雅的写法
/* @article https://johnresig.com/blog/simple-javascript-inheritance/
 * Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
(function () {
    var initializing = false, fnTest = /xyz/.test(function () {
        xyz;
    }) ? /\b_super\b/ : /.*/;
    // The base Class implementation (does nothing)
    this.Class = function () {
    };
    // Create a new Class that inherits from this class
    Class.extend = function (prop) {
        var _super = this.prototype;
        // Instantiate a base class (but only create the instance,
        // don't run the init constructor)
        initializing = true;
        var prototype = new this();
        initializing = false;
        // Copy the properties over onto the new prototype
        for (var name in prop) {
            // Check if we're overwriting an existing function
            prototype[name] = typeof prop[name] == "function" &&
            typeof _super[name] == "function" && fnTest.test(prop[name]) ?
                    (function (name, fn) {
                        return function () {
                            var tmp = this._super;
                            // Add a new ._super() method that is the same method
                            // but on the super-class
                            this._super = _super[name];
                            // The method only need to be bound temporarily, so we
                            // remove it when we're done executing
                            var ret = fn.apply(this, arguments);
                            this._super = tmp;
                            return ret;
                        };
                    })(name, prop[name]) :
                    prop[name];
        }
        // The dummy class constructor
        function Class() {
            // All construction is actually done in the init method
            if (!initializing && this.init)
                this.init.apply(this, arguments);
        }
        // Populate our constructed prototype object
        Class.prototype = prototype;
        // Enforce the constructor to be what we expect
        Class.prototype.constructor = Class;
        // And make this class extendable
        Class.extend = arguments.callee;
        return Class;
    };
})();
线上链接。这个继承是大牛写的,是我见过最简洁写法了,但是在工作中,一直没看到有人在子类方法内,要用到父类方法,直接使用this._super方法,还有init方法construction,也只会调用一次。继承中构造函数保持在原型链中。这个实现不支持继承静态方法,但以后如果有需求,我会尽量用这个方法。
最繁重的写法
var Class = (function () {
    // Class
    // -----------------
    // Thanks to:
    //  - http://mootools.net/docs/core/Class/Class
    //  - http://ejohn.org/blog/simple-javascript-inheritance/
    //  - https://github.com/ded/klass
    //  - http://documentcloud.github.com/backbone/#Model-extend
    //  - https://github.com/joyent/node/blob/master/lib/util.js
    //  - https://github.com/kissyteam/kissy/blob/master/src/seed/src/kissy.js
    // The base Class implementation.
    function Class(o) {
        // Convert existed function to Class.
        if (!(this instanceof Class) && isFunction(o)) {
            return classify(o)
        }
    }
    // Create a new Class.
    //
    //  var SuperPig = Class.create({
    //    Extends: Animal,
    //    Implements: Flyable,
    //    initialize: function() {
    //      SuperPig.superclass.initialize.apply(this, arguments)
    //    },
    //    Statics: {
    //      COLOR: 'red'
    //    }
    // })
    //
    Class.create = function (parent, properties) {
        if (!isFunction(parent)) {
            properties = parent
            parent = null
        }
        properties || (properties = {})
        parent || (parent = properties.Extends || Class)
        properties.Extends = parent
        // The created class constructor
        function SubClass() {
            // Call the parent constructor.
            parent.apply(this, arguments)
            // Only call initialize in self constructor.
            if (this.constructor === SubClass && this.initialize) {
                this.initialize.apply(this, arguments)
            }
        }
        // Inherit class (static) properties from parent.
        if (parent !== Class) {
            mix(SubClass, parent, parent.StaticsWhiteList)
        }
        // Add instance properties to the subclass.
        implement.call(SubClass, properties)
        // Make subclass extendable.
        return classify(SubClass)
    }
    function implement(properties) {
        var key, value
        for (key in properties) {
            value = properties[key]
            if (Class.Mutators.hasOwnProperty(key)) {
                Class.Mutators[key].call(this, value)
            } else {
                this.prototype[key] = value
            }
        }
    }
    // Create a sub Class based on `Class`.
    Class.extend = function (properties) {
        properties || (properties = {})
        properties.Extends = this
        return Class.create(properties)
    }
    function classify(cls) {
        cls.extend = Class.extend
        cls.implement = implement
        return cls
    }
    // Mutators define special properties.
    Class.Mutators = {
        'Extends': function (parent) {
            var existed = this.prototype
            var proto = createProto(parent.prototype)
            // Keep existed properties.
            mix(proto, existed)
            // Enforce the constructor to be what we expect.
            proto.constructor = this
            // Set the prototype chain to inherit from `parent`.
            this.prototype = proto
            // Set a convenience property in case the parent's prototype is
            // needed later.
            this.superclass = parent.prototype
        },
        'Implements': function (items) {
            isArray(items) || (items = [items])
            var proto = this.prototype, item
            while (item = items.shift()) {
                mix(proto, item.prototype || item)
            }
        },
        'Statics': function (staticProperties) {
            mix(this, staticProperties)
        }
    }
    // Shared empty constructor function to aid in prototype-chain creation.
    function Ctor() {
    }
    // See: http://jsperf.com/object-create-vs-new-ctor
    var createProto = Object.__proto__ ?
            function (proto) {
                return {__proto__: proto}
            } :
            function (proto) {
                Ctor.prototype = proto
                return new Ctor()
            }
    // Helpers
    // ------------
    function mix(r, s, wl) {
        // Copy "all" properties including inherited ones.
        for (var p in s) {
            if (s.hasOwnProperty(p)) {
                if (wl && indexOf(wl, p) === -1) continue
                // 在 iPhone 1 代等设备的 Safari 中,prototype 也会被枚举出来,需排除
                if (p !== 'prototype') {
                    r[p] = s[p]
                }
            }
        }
    }
    var toString = Object.prototype.toString
    var isArray = Array.isArray || function (val) {
                return toString.call(val) === '[object Array]'
            }
    var isFunction = function (val) {
        return toString.call(val) === '[object Function]'
    }
    var indexOf = Array.prototype.indexOf ?
            function (arr, item) {
                return arr.indexOf(item)
            } :
            function (arr, item) {
                for (var i = 0, len = arr.length; i < len; i++) {
                    if (arr[i] === item) {
                        return i
                    }
                }
                return -1
            }
    return Class
})()
线上链接。这个继承是功能最全面的,包括类实现里,怎么实现静态方法,但是它的语法糖太多了,Extends、Implements、Statics、initialize,继承中的构造函数提出来,放在当前类的构造函数中执行,new初始化时的钩子,是initialize,只会调用一次,继承中initialize也可以调用。
brix里的实现
// http://g.alicdn.com/thx/brix-release/1.0.0-beta.9/brix-base/dist/base-debug.js
var _ = {}
var toString = Object.prototype.toString
_.each = function (obj, iterator, context) {
    if (obj === null || obj === undefined) return obj
    if (obj.forEach) {
        obj.forEach(iterator, context);
    } else if (obj.length === +obj.length) {
        for (var i = 0, length = obj.length; i < length; i++) {
            iterator.call(context, obj[i], i, obj)
        }
    } else {
        for (var prop in obj) {
            iterator.call(context, obj[prop], prop, obj)
        }
    }
    return obj
}
_.each('Boolean Number String Function Array Date RegExp Object Error'.split(' '), function (name) {
    _['is' + name] = function (obj) {
        return toString.call(obj) == '[object ' + name + ']'
    }
})
_.extend = function () {
    var target = arguments[0]
    var index = 1
    var length = arguments.length
    var deep = false
    var options, name, src, copy, clone
    if (typeof target === "boolean") {
        deep = target
        target = arguments[index] || {}
        index++
    }
    if (typeof target !== "object" && typeof target !== "function") {
        target = {}
    }
    if (length === 1) {
        target = this
        index = 0
    }
    for (; index < length; index++) {
        options = arguments[index]
        if (!options) continue
        for (name in options) {
            src = target[name]
            copy = options[name]
            if (target === copy) continue
            if (copy === undefined) continue
            if (deep && (_.isArray(copy) || _.isObject(copy))) {
                if (_.isArray(copy)) clone = src && _.isArray(src) ? src : []
                if (_.isObject(copy)) clone = src && _.isObject(src) ? src : {}
                target[name] = _.extend(deep, clone, copy)
            } else {
                target[name] = copy
            }
        }
    }
    return target
}
/*
 This function is loosely inspired by Backbone.js.
 http://backbonejs.org
 */
function extend(protoProps, staticProps) {
    var parent = this
    // 构造函数 Initialize constructor
    var constructor = protoProps && protoProps.hasOwnProperty('constructor') ?
            protoProps.constructor : // 自定义构造函数 Custom constructor
            parent // 父类构造函数 Base constructor
    // 子类 Subclass
    var child = function () {
        parent.__x_created_with = child.__x_created_with
        var instance = constructor.apply(this, arguments) || this
        // instance.options vs parameter options
        var options = arguments[0]
        if (options && !instance.hasOwnProperty('options')) {
            instance.options = _.extend(true, {}, this.options, options)
        }
        // 如果模块带有 __x_created_with,则一切初始化行为都交给第三方;否则调用 .create() 方法。
        // If the child module has a property named as __x_created_with, the third-library will be response for the rest of initialization actions.
        // If not, the child module will call the `.create()`.
        if (!child.__x_created_with && instance.created && instance.constructor === child) {
            instance.created.apply(instance, instance.created.length ? [instance.options] : []) // @edit
        }
        return instance
    }
    // 静态属性 Static properties
    _.extend(child, parent, staticProps)
    // 原型链 Build prototype chain.
    var Surrogate = function () {
//      this.constructor = constructor // @remove
    }
    Surrogate.prototype = parent.prototype
    child.prototype = new Surrogate()
    child.prototype.constructor = child // @add
    // 原型属性 Copy prototype properties from the parameter protoProps to the prototype of child
    if (protoProps) _.extend(child.prototype, protoProps)
    // Add keyword __super__
    child.__super__ = parent.prototype
    child.extend = extend
    return child
}
function Brix() {
}
Brix.prototype = {
    created: function () {
        if (this.init) this.init()
        if (this.render) this.render()
    },
    constructor: Brix // @add
}
Brix.extend = extend
是Brix Base里关于继承的实现,因为为了支持框架Brix Loader,所以继承里做了特殊处理,比如options参数,比如__x_created_with,继承中的构造函数提出来,放在当前类的构造函数中执行,new时初始化钩子,是created方法调用init、render,所以初始化语句可以放在init、render,按正常结果只调用一次,但这里调用了两次,重复了。
magix里实现
magix中View如何实现继承?也是类似brix,但它不包含任何语法糖,new初始化钩子,是
View.extend = function(props, statics, ctor) {
第三个参数ctor是初始化钩子,这里会多次调用
总结
为了实现类似Person.extend能生成新类,extend要向封装传入原型上方法,父类,静态方法,每次执行extend时要定义新类的构造函数。返回的新类也能extend再生成子类。
封装内,将父类的构造函数和原型拆分。新类的构造函数执行父类的构造函数,新类的原型指向Object.create(父类的原型)。构造函数在实例化时才执行,原型链实现,在实现继承时就执行。
新类的构造函数中执行父类的构造函数,父类的构造函数再执行祖先的构造函数...,直到最顶层。最顶层构造函数可自由实现。在simple-inherit中是封装外面的Class,在brix中是首次直接赋值了extend方法的类。complex-inherit中,是由Class.create传入的。
实例化类的时候,要自动执行初始化的操作,正常是在构造函数中实现的,extend封装里的构造函数是统一写死的,无法自由做一些初始化,要在构造函数里提供个钩子,构造函数执行这个钩子函数,钩子函数,在定义新类的时候传入,也就是Person.extend时传入。
钩子一般是定义在原型上的某方法,比如initialize方法,因为构造函数里是调父类的构造函数,一直到最顶层基类,也要多次执行构造函数内钩子吗?钩子是这样执行的this.initialize.apply(this, arguments),this在每次执行时都不变的,也没必要多次执行,只要执行一次即可。并且只执行原型链中,第一个有钩子方法的原型,剩下的都不执行了。
实现原型链继承时,要注意原型的constructor属性,为了子类方法能调父类方法,给每个类加个superclass属性,指向父类的原型对象。
mix
	// https://g.alicdn.com/mm/pubplus/0.4.12/app_debug/exts/arale/class.js
    function mix(r, s, wl) {
      // Copy "all" properties including inherited ones.
      for (var p in s) {
        if (s.hasOwnProperty(p)) {
          if (wl && indexOf(wl, p) === -1) continue
          // 在 iPhone 1 代等设备的 Safari 中,prototype 也会被枚举出来,需排除
          if (p !== 'prototype') {
            r[p] = s[p]
          }
        }
      }
    }
extend在库里实现
underscore
将后面对象的自有可枚举属性,拷贝到第一个对象,并返回第一个对象
  // http://g.alicdn.com/thx/brix-release/1.0.0-beta.9/underscore/underscore.js
  // Extend a given object with all the properties in passed-in object(s).
  _.extend = function(obj) {
    if (!_.isObject(obj)) return obj;
    var source, prop;
    for (var i = 1, length = arguments.length; i < length; i++) {
      source = arguments[i];
      for (prop in source) {
        if (hasOwnProperty.call(source, prop)) {
            obj[prop] = source[prop];
        }
      }
    }
    return obj;
  };
jquery
支持深度拷贝,深拷贝除了支持对象还包括数组,改变第一个对象,并返回第一个对象
// http://g.alicdn.com/thx/brix-release/1.0.0-beta.9/jquery/dist/jquery.js
jQuery.extend = jQuery.fn.extend = function() {
	var src, copyIsArray, copy, name, options, clone,
		target = arguments[ 0 ] || {},
		i = 1,
		length = arguments.length,
		deep = false;
	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		// skip the boolean and the target
		target = arguments[ i ] || {};
		i++;
	}
	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
		target = {};
	}
	// extend jQuery itself if only one argument is passed
	if ( i === length ) {
		target = this;
		i--;
	}
	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( ( options = arguments[ i ] ) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];
				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}
				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
					( copyIsArray = jQuery.isArray( copy ) ) ) ) {
					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && jQuery.isArray( src ) ? src : [];
					} else {
						clone = src && jQuery.isPlainObject( src ) ? src : {};
					}
					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );
				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}
	// Return the modified object
	return target;
};
kissy1.3中有关对象的方法
mix
改变并返回第一个参数,下面实现方法中MIX_CIRCULAR_DETECTION标记,感觉是为了调试,看deep了几次
/*
 * for example:
 *     @example
 *     var t = {};
 *     S.mix({x: {y: 2, z: 4}}, {x: {y: 3, a: t}}, {deep: TRUE}) => {x: {y: 3, z: 4, a: {}}}, a !== t
 *     S.mix({x: {y: 2, z: 4}}, {x: {y: 3, a: t}}, {deep: TRUE, overwrite: false}) => {x: {y: 2, z: 4, a: {}}}, a !== t
 *     S.mix({x: {y: 2, z: 4}}, {x: {y: 3, a: t}}, 1) => {x: {y: 3, a: t}}
 */
mix: function (r, s, ov, wl, deep) {
    if (typeof ov === 'object') {
        wl = ov['whitelist'];
        deep = ov['deep'];
        ov = ov['overwrite'];
    }
    var cache = [],
            c,
            i = 0;
    mixInternal(r, s, ov, wl, deep, cache);
    while (c = cache[i++]) {
        delete c[MIX_CIRCULAR_DETECTION];
    }
    return r;
}
function mixInternal(r, s, ov, wl, deep, cache) {
    if (!s || !r) {
        return r;
    }
    if (ov === undefined) {
        ov = TRUE;
    }
    var i = 0, p, keys, len;
    // 记录循环标志
    s[MIX_CIRCULAR_DETECTION] = r;
    // 记录被记录了循环标志的对像
    cache.push(s);
    if (wl) {
        len = wl.length;
        for (i = 0; i < len; i++) {
            p = wl[i];
            if (p in s) {
                _mix(p, r, s, ov, wl, deep, cache);
            }
        }
    } else {
        // mix all properties
        keys = S.keys(s);
        len = keys.length;
        for (i = 0; i < len; i++) {
            p = keys[i];
            if (p != MIX_CIRCULAR_DETECTION) {
                // no hasOwnProperty judge!
                _mix(p, r, s, ov, wl, deep, cache);
            }
        }
    }
    return r;
}
function _mix(p, r, s, ov, wl, deep, cache) {
    // 要求覆盖
    // 或者目的不存在
    // 或者深度mix
    if (ov || !(p in r) || deep) {
        var target = r[p],
                src = s[p];
        // prevent never-end loop
        if (target === src) {
            // S.mix({},{x:undefined})
            if (target === undefined) {
                r[p] = target;
            }
            return;
        }
        // 来源是数组和对象,并且要求深度 mix
        if (deep && src && (S.isArray(src) || S.isPlainObject(src))) {
            if (src[MIX_CIRCULAR_DETECTION]) {
                r[p] = src[MIX_CIRCULAR_DETECTION];
            } else {
                // 目标值为对象或数组,直接 mix
                // 否则 新建一个和源值类型一样的空数组/对象,递归 mix
                var clone = target && (S.isArray(target) || S.isPlainObject(target)) ?
                        target :
                        (S.isArray(src) ? [] : {});
                r[p] = clone;
                mixInternal(clone, src, ov, wl, TRUE, cache);
            }
        } else if (src !== undefined && (ov || !(p in r))) {
            r[p] = src;
        }
    }
}
merge
合并所有obj到返回新
merge: function (var_args) {
    var_args = S.makeArray(arguments);
    var o = {},
        i,
        l = var_args.length;
    for (i = 0; i < l; i++) {
        S.mix(o, var_args[i]);
    }
    return o;
},
augment
只对原型对象进行复制,改变并返回第一个参数
augment: function (r, var_args) {
    var args = S.makeArray(arguments),
        len = args.length - 2,
        i = 1,
        ov = args[len],
        wl = args[len + 1];
    if (!S.isArray(wl)) {
        ov = wl;
        wl = undefined;
        len++;
    }
    if (!S.isBoolean(ov)) {
        ov = undefined;
        len++;
    }
    for (; i < len; i++) {
        S.mix(r.prototype, args[i].prototype || args[i], ov, wl);
    }
    return r;
},
extend
继承的实现,跟上面封装的继承相比,还是有缺点的,首先新类的构造函数执行时候,父类的构造函数不会自动执行,总觉得superclass的指向的原型,中间多了一层
extend: function (r, s, px, sx) {
    if (!s || !r) {
        return r;
    }
    var sp = s.prototype,
        rp;
    // add prototype chain
    rp = createObject(sp, r);
    r.prototype = S.mix(rp, r.prototype);
    r.superclass = createObject(sp, s);
    // add prototype overrides
    if (px) {
        S.mix(rp, px);
    }
    // add object overrides
    if (sx) {
        S.mix(r, sx);
    }
    return r;
},
function Empty() {
}
function createObject(proto, constructor) {
    var newProto;
    if (ObjectCreate) {
        newProto = ObjectCreate(proto);
    } else {
        Empty.prototype = proto;
        newProto = new Empty();
    }
    newProto.constructor = constructor;
    return newProto;
}
更多例子以及在例子中,我对继承的摸索http://sprying.github.io/webtest/class/index.html
js中有关类、对象的增强函数的更多相关文章
- js中的类和对象以及自定义对象
		js中的类 1.类的声明 function Person(name,age){ this.name=name; this.age=age; this.test=function(a){ alert(a ... 
- JS中定义类的方法
		JS中定义类的方式有很多种: 1.工厂方式 function Car(){ var ocar = new Object; ocar.color = "blue" ... 
- JS中定义类的方法<转>
		转载地址:http://blog.csdn.net/sdlfx/article/details/1842218 PS(个人理解): 1) 类通过prototype定义的成员(方法或属性),是每个类对象 ... 
- js中escape对应的C#解码函数 UrlDecode
		js中escape对应的C#解码函数 System.Web.HttpUtility.UrlDecode(s),使用过程中有以下几点需要注意 js中escape对应的C#解码函数 System.We ... 
- JS中的面相对象
		1.使用Object或对象字面量创建对象 JS中最基本创建对象的方式: var student = new Object(); student.name = "easy"; stu ... 
- JS中的event 对象详解
		JS中的event 对象详解 JS的event对象 Event属性和方法:1. type:事件的类型,如onlick中的click:2. srcElement/target:事件源,就是发生事件的 ... 
- js中两个对象的比较
		代码取自于underscore.js 1.8.3的isEqual函数. 做了一些小小的修改,主要是Function的比较修改. 自己也加了一些代码解读. <!DOCTYPE html> & ... 
- js中的json对象详细介绍
		JSON一种简单的数据格式,比xml更轻巧,在JavaScript中处理JSON数据不需要任何特殊的API或工具包,下面为大家详细介绍下js中的json对象, 1.JSON(JavaScript Ob ... 
- js中如何访问对象和数组
		js中如何访问对象和数组 一.总结 一句话总结:js访问对象点和中括号,访问数组的话就是中括号 对象 . [] 数组 [] 1.js访问对象的两种方式? . [] 可以使用下面两种方式访问对象的属性和 ... 
- js动态创建类对象
		1.定义函数,函数中定义类对象 f1=function(){ //定义类 function Pannel(name){ this.name = name; this.print = function( ... 
随机推荐
- You must restart adb and Eclipse.
			打开Eclipse运行android 程序发现虚拟机启动不了提示 You must restart adb and Eclipse. 如下方式适用于端口占用的情况: 1.netstat -ano|f ... 
- Reporting Service服务SharePoint集成模式安装配置(3、4、安装sharepoint 2010必备组件及产品)
			Reporting Service服务SharePoint集成模式安装配置 第三步和第四部 第三步 安装sharepoint 2010必备组件 1.安装SharePoint2010必备组件,执行Pre ... 
- httpclient 解析excel
			http://www.blogjava.net/jayslong/archive/2011/04/21/convert_xls_and_xlsx_to_csv.html 分享用Java将Excel的x ... 
- git .gitignore忽略规则不生效解决办法
			忽略规则不生效, 原因是.gitignore只能忽略那些原来没有被track的文件, 如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的. 那么解决方法就是先把本地缓存删除(改变成 ... 
- sublime基本命令和使用
			Ctrl+Shift+p Package Control Ctrl+D 选词 (反复按快捷键,即可继续向下同时选中下一个相同的文本进行同时编辑)Ctrl+G 跳转到相应的行Ctrl+J 合并行(已选 ... 
- BZOJ 4817: [Sdoi2017]树点涂色(LCT+树剖+线段树)
			题目描述 Bob有一棵 nn 个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. Bob ... 
- 【转】【C++专题】C++ sizeof 使用规则及陷阱分析
			提示:下文例子都经过Visual C++ 6.0验证,平台为win32 Windows. 一.什么是sizeof 首先看一下sizeof在msdn上的定义: The sizeof keyword gi ... 
- Nginx反向代理与负载简单实现
			反向代理 1.proxy_pass 通过反向代理把请求转发到百度 2.proxy_pass 既可以是ip地址,也可以是域名,同时还可以指定端口 3.proxy_pass 指定的地址携带了URI,如果前 ... 
- JavaWeb学习笔记(十八)—— DBUtils的使用
			一.DBUtils概述 1.1 什么是DBUtils commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbuti ... 
- js高级程序设计 笔记 --- 错误处理、json和ajax
			1,错误处理 1,try-catch语句 try{可能导致错误的代码} catch(error) {在错误发生时该怎么处理} error.message是所有浏览器都支持的属性. finally语句是 ... 
