- 浏览: 91589 次
- 性别:
- 来自: 武汉
-
文章分类
最新评论
-
zhaohaolin:
哟,龙哥,你还搞C,好高大上的东西啊
xcode初探 -
robinqu:
又改了一些小错误~
[更新20100922]jQuery Location Select 插件- 地址联动、地理检测 -
robinqu:
kimm 写道这个功能不错,就是应用有点局限,内网就不好用了。 ...
[更新20100922]jQuery Location Select 插件- 地址联动、地理检测 -
robinqu:
更新了⋯⋯把代码重写了一次⋯⋯大家可以实现任何种类的联动,以及 ...
[更新20100922]jQuery Location Select 插件- 地址联动、地理检测 -
robinqu:
truth315 写道不好意思了,compu指的是getAre ...
JavaScript Prototype基础
Duck Typing
Duck Typing的假设如下,如果一个对象实现了一个类中的所有方法,那么这个对象就是这个类的实例。
Duck Typing和之前讲的“方法借用”一起就非常有用,在Duck Typing的假设下,你的确可以说之前例子中的Rectangle是GenricEquals的实例。但是instanceof并不这么认为,我们只有自己写一个方法来判断:
这个borrow()函数严格的判断这个对象是否实现了类中的所有方法,但有时候我们的Duck Typing需要更加灵活。我们只需要这个对象提供了同名方法,以及方法的参数一致就可以了。
下面是实现这种判定的函数:
下面给出一个实际的使用环境。假设Comparable()是一个通用的API接口,我们用provide()函数就可以判定某个对象是否拥有了Comparable中的同名方法,也就是有没有类似的compareTo()方法:
最后给一个定义类的函数,老外实在太NB了,自己看注释吧,虽然很长不过很清晰:
演示一下这东西怎么用:
引用
If it implements all the methods defined by a class, it is an instance of that class.
Duck typing is particularly useful in conjunction with classes that "borrow" methods from other classes. Earlier in the chapter, a Rectangle class borrowed the implementation of an equals( ) method from another class named GenericEquals. Thus, you can consider any Rectangle instance to also be an instance of GenericEquals. The instanceof operator will not report this, but you can define a method that will.
Duck typing is particularly useful in conjunction with classes that "borrow" methods from other classes. Earlier in the chapter, a Rectangle class borrowed the implementation of an equals( ) method from another class named GenericEquals. Thus, you can consider any Rectangle instance to also be an instance of GenericEquals. The instanceof operator will not report this, but you can define a method that will.
Duck Typing的假设如下,如果一个对象实现了一个类中的所有方法,那么这个对象就是这个类的实例。
Duck Typing和之前讲的“方法借用”一起就非常有用,在Duck Typing的假设下,你的确可以说之前例子中的Rectangle是GenricEquals的实例。但是instanceof并不这么认为,我们只有自己写一个方法来判断:
// Return true if each of the method properties in c.prototype have been // borrowed by o. If o is a function rather than an object, we // test the prototype of o rather than o itself. // Note that this function requires methods to be copied, not // reimplemented. If a class borrows a method and then overrides it, // this method will return false. function borrows(o, c) { // If we are an instance of something, then of course we have its methods if (o instanceof c) return true; // It is impossible to test whether the methods of a built-in type have // been borrowed, since the methods of built-in types are not enumerable. // We return undefined in this case as a kind of "I don't know" answer // instead of throwing an exception. Undefined behaves much like false, // but can be distinguished from false if the caller needs to. if (c == Array || c == Boolean || c == Date || c == Error || c == Function || c == Number || c == RegExp || c == String) return undefined; if (typeof o == "function") o = o.prototype; var proto = c.prototype; for(var p in proto) { // Ignore properties that are not functions if (typeof proto[p] != "function") continue; if (o[p] != proto[p]) return false; } return true; }
引用
The borrows( ) method of Example 9-7 is relatively strict: it requires the object o to have exact copies of the methods defined by the class c.
TRue duck typing is more flexible: o should be considered an instance of c as long as it provides methods that look like methods of c.
TRue duck typing is more flexible: o should be considered an instance of c as long as it provides methods that look like methods of c.
这个borrow()函数严格的判断这个对象是否实现了类中的所有方法,但有时候我们的Duck Typing需要更加灵活。我们只需要这个对象提供了同名方法,以及方法的参数一致就可以了。
下面是实现这种判定的函数:
// Return true if o has methods with the same name and arity as all // methods in c.prototype. Otherwise, return false. Throws an exception // if c is a built-in type with nonenumerable methods. function provides(o, c) { // If o actually is an instance of c, it obviously looks like c if (o instanceof c) return true; // If a constructor was passed instead of an object, use its prototype if (typeof o == "function") o = o.prototype; // The methods of built-in types are not enumerable, and we return // undefined. Otherwise, any object would appear to provide any of // the built-in types. if (c == Array || c == Boolean || c == Date || c == Error || c == Function || c == Number || c == RegExp || c == String) return undefined; var proto = c.prototype; for(var p in proto) { // Loop through all properties in c.prototype // Ignore properties that are not functions if (typeof proto[p] != "function") continue; // If o does not have a property by the same name, return false if (!(p in o)) return false; // If that property is not a function, return false if (typeof o[p] != "function") return false; // If the two functions are not declared with the same number // of arguments, return false. if (o[p].length != proto[p].length) return false; } // If all the methods check out, we can finally return true. return true; }
下面给出一个实际的使用环境。假设Comparable()是一个通用的API接口,我们用provide()函数就可以判定某个对象是否拥有了Comparable中的同名方法,也就是有没有类似的compareTo()方法:
function Comparable( ) {} Comparable.prototype.compareTo = function(that) { throw "Comparable.compareTo( ) is abstract. Don't invoke it!"; } // Check whether objects o and p can be compared // They must be of the same type, and that type must be comparable if (o.constructor == p.constructor && provides(o, Comparable)) { var order = o.compareTo(p); }
最后给一个定义类的函数,老外实在太NB了,自己看注释吧,虽然很长不过很清晰:
/** * defineClass( ) -- a utility function for defining JavaScript classes. * * This function expects a single object as its only argument. It defines * a new JavaScript class based on the data in that object and returns the * constructor function of the new class. This function handles the repetitive * tasks of defining classes: setting up the prototype object for correct * inheritance, copying methods from other types, and so on. * * The object passed as an argument should have some or all of the * following properties: * * name: The name of the class being defined. * If specified, this value will be stored in the classname * property of the prototype object. * * extend: The constructor of the class to be extended. If omitted, * the Object( ) constructor will be used. This value will * be stored in the superclass property of the prototype object. * * construct: The constructor function for the class. If omitted, a new * empty function will be used. This value becomes the return * value of the function, and is also stored in the constructor * property of the prototype object. * * methods: An object that specifies the instance methods (and other shared * properties) for the class. The properties of this object are * copied into the prototype object of the class. If omitted, * an empty object is used instead. Properties named * "classname", "superclass", and "constructor" are reserved * and should not be used in this object. * * statics: An object that specifies the static methods (and other static * properties) for the class. The properties of this object become * properties of the constructor function. If omitted, an empty * object is used instead. * * borrows: A constructor function or array of constructor functions. * The instance methods of each of the specified classes are copied * into the prototype object of this new class so that the * new class borrows the methods of each specified class. * Constructors are processed in the order they are specified, * so the methods of a class listed at the end of the array may * overwrite the methods of those specified earlier. Note that * borrowed methods are stored in the prototype object before * the properties of the methods object above. Therefore, * methods specified in the methods object can overwrite borrowed * methods. If this property is not specified, no methods are * borrowed. * * provides: A constructor function or array of constructor functions. * After the prototype object is fully initialized, this function * verifies that the prototype includes methods whose names and * number of arguments match the instance methods defined by each * of these classes. No methods are copied; this is simply an * assertion that this class "provides" the functionality of the * specified classes. If the assertion fails, this method will * throw an exception. If no exception is thrown, any * instance of the new class can also be considered (using "duck * typing") to be an instance of these other types. If this * property is not specified, no such verification is performed. **/ function defineClass(data) { // Extract the fields we'll use from the argument object. // Set up default values. var classname = data.name; var superclass = data.extend || Object; var constructor = data.construct || function( ) {}; var methods = data.methods || {}; var statics = data.statics || {}; var borrows; var provides; // Borrows may be a single constructor or an array of them. if (!data.borrows) borrows = []; else if (data.borrows instanceof Array) borrows = data.borrows; else borrows = [ data.borrows ]; // Ditto for the provides property. if (!data.provides) provides = []; else if (data.provides instanceof Array) provides = data.provides; else provides = [ data.provides ]; // Create the object that will become the prototype for our class. var proto = new superclass( ); // Delete any noninherited properties of this new prototype object. for(var p in proto) if (proto.hasOwnProperty(p)) delete proto[p]; // Borrow methods from "mixin" classes by copying to our prototype. for(var i = 0; i < borrows.length; i++) { var c = data.borrows[i]; borrows[i] = c; // Copy method properties from prototype of c to our prototype for(var p in c.prototype) { if (typeof c.prototype[p] != "function") continue; proto[p] = c.prototype[p]; } } // Copy instance methods to the prototype object // This may overwrite methods of the mixin classes for(var p in methods) proto[p] = methods[p]; // Set up the reserved "constructor", "superclass", and "classname" // properties of the prototype. proto.constructor = constructor; proto.superclass = superclass; // classname is set only if a name was actually specified. if (classname) proto.classname = classname; // Verify that our prototype provides all of the methods it is supposed to. for(var i = 0; i < provides.length; i++) { // for each class var c = provides[i]; for(var p in c.prototype) { // for each property if (typeof c.prototype[p] != "function") continue; // methods only if (p == "constructor" || p == "superclass") continue; // Check that we have a method with the same name and that // it has the same number of declared arguments. If so, move on if (p in proto && typeof proto[p] == "function" && proto[p].length == c.prototype[p].length) continue; // Otherwise, throw an exception throw new Error("Class " + classname + " does not provide method "+ c.classname + "." + p); } } // Associate the prototype object with the constructor function constructor.prototype = proto; // Copy static properties to the constructor for(var p in statics) constructor[p] = data.statics[p]; // Finally, return the constructor function return constructor; }
演示一下这东西怎么用:
// A Comparable class with an abstract method // so that we can define classes that "provide" Comparable. var Comparable = defineClass({ name: "Comparable", methods: { compareTo: function(that) { throw "abstract"; } } }); // A mixin class with a usefully generic equals( ) method for borrowing var GenericEquals = defineClass({ name: "GenericEquals", methods: { equals: function(that) { if (this == that) return true; var propsInThat = 0; for(var name in that) { propsInThat++; if (this[name] !== that[name]) return false; } // Now make sure that this object doesn't have additional props var propsInThis = 0; for(name in this) propsInThis++; // If this has additional properties, then they are not equal if (propsInThis != propsInThat) return false; // The two objects appear to be equal. return true; } } }); // A very simple Rectangle class that provides Comparable var Rectangle = defineClass({ name: "Rectangle", construct: function(w,h) { this.width = w; this.height = h; }, methods: { area: function( ) { return this.width * this.height; }, compareTo: function(that) { return this.area( ) - that.area( ); } }, provides: Comparable }); // A subclass of Rectangle that chains to its superclass constructor, // inherits methods from its superclass, defines an instance method and // a static method of its own, and borrows an equals( ) method. var PositionedRectangle = defineClass({ name: "PositionedRectangle", extend: Rectangle, construct: function(x,y,w,h) { this.superclass(w,h); // chain to superclass this.x = x; this.y = y; }, methods: { isInside: function(x,y) { return x > this.x && x < this.x+this.width && y > this.y && y < this.y+this.height; } }, statics: { comparator: function(a,b) { return a.compareTo(b); } }, borrows: [GenericEquals] });
发表评论
-
WebApp在移动端的涅盘- 另类的移动端应用程序开发
2010-09-27 22:35 4539同时欢迎到我的BLOG讨 ... -
ScriptDoc的Notation规则
2010-01-23 19:37 1808这个还是蛮重要的,以前就一直很羡慕Java有一套标准来着: 转 ... -
关于google.setOnLoadCallback()的一点研究
2010-01-12 10:01 6173google.setOnLoadCallback()是goog ... -
ECMA 推出 JavaScript 5
2009-12-28 21:17 1670转发自http://www.comsharp.co ... -
Javascript 事件编程 (二)
2009-09-18 21:28 1663Event Handlers and the this Key ... -
Javascript 事件编程 (一)
2009-09-04 15:27 1291Events and Event Handling 事件和事件 ... -
Javascript CSS编程 (一)元素定位、透明、内联样式
2009-09-03 14:29 2110Querying Element Position and S ... -
Javascript CSS编程 (二)Computed Styles、Class修改、操作样式表
2009-09-03 13:15 5395Scripting Computed Styles 计算样式 ... -
Javascript DHTML动画
2009-09-03 13:00 1270JS实现的动画效果多半 ... -
Javascript IE4 DOM
2009-09-02 17:14 1048很多IE独有的DOM特性是沿袭自IE4的,所以有必要看看IE4 ... -
Javascript 操控选择文本
2009-09-02 17:02 1296Querying Selected Text 查询选择的文本 ... -
Javascript 寻找文档元素
2009-09-02 16:51 2382Finding Elements in a Document ... -
Javascript 窗口的几何关系和相关方法、属性
2009-09-02 10:47 1187Window Geometry 窗口几何关系 引用Scree ... -
JavaScript window下面的常用函数、属性
2009-09-02 10:30 1266我们常用的一些函数都是全局对象window下面的。这里将其梳理 ... -
JavaScript 在浏览器中的相关概念:执行环境、引入脚本、安全策略等
2009-09-02 09:32 1423The Window as Global Execution ... -
JavaScript Namespace模拟
2009-07-15 18:53 1604做JavaScript的大型项目比较痛苦,它没有namespa ... -
JavaScript 判定对象类型
2009-07-15 16:53 1423判定JS的对象类型基本 ... -
JavaScript Class模拟深入 - 继承、子类
2009-07-15 16:27 1772Superclasses and Subclasses ... -
javascript this 关键字小提示
2009-07-14 22:01 1210来自:http://www.macji.com/2009/01 ... -
JavaScript Class模拟基础
2009-07-14 16:39 1165Simulating Classes in JavaScrip ...
相关推荐
此外,JavaScript的鸭子类型(Duck Typing)原则,即“如果它走起路来像鸭子,叫起来也像鸭子,那么它就是鸭子”,意味着我们可以通过检查对象的方法和属性来判断它是否符合某种“接口”。 一种常见的模拟接口的...
在JavaScript中,多态主要通过函数重写(override)和鸭子类型(duck typing)实现。鸭子类型是一种“如果它走起路来像鸭子,叫起来也像鸭子,那么它就是鸭子”的哲学,它不关心对象的实际类型,只关注对象的行为。...
在JavaScript中,多态可以通过方法重写和鸭子类型(duck typing)来实现,即不关心对象的具体类型,只要该对象具有期望的行为即可。 #### 四、JavaScript语言基础 在深入探讨面向对象编程之前,了解JavaScript的基础...
另一个在JavaScript中实现接口的方式是使用鸭子类型(Duck Typing),这是一种根据对象的行为(方法和属性)而不是其类型来判断对象是否符合某种标准的编程模式。如果一个对象具有与接口所需相同的方法和属性,那么...
同时,JavaScript的鸭子类型(Duck Typing)也是一大特色,即“如果它走起路来像鸭子,叫起来也像鸭子,那么它就是鸭子”,强调行为而非类型。 在实际开发中,我们通常会利用模块系统(CommonJS, ES Modules)组织...