【类和模块】类的扩充(Extension of [class and module])

类的扩充

JavaScript中基于原型的继承机制是动态的:对象从其原型继承属性,如果创建对象之后原型的属性发生改变,也会影响到继承这个原型的所有实例对象。这意味着我们可以通过给原型对象添加新方法来扩充JavaScript类。这里我们给上例中的Complex类添加方法来计算复数的共貌复数(两个实部相等,虚部互为相反教的复数互为共辄复教)。
// 返回当前复数的共辄复数
Complex.prototype.conj = function() { return new Complex(this.r, -this.i); };

JavaScript中基于原型的继承机制是动态的:对象从其原型继承属性,如果创建对象之后原型的属性发生改变,也会影响到继承这个原型的所有实例对象。这意味着我们可以通过给原型对象添加新方法来扩充JavaScript类。这里我们给上例中的Complex类添加方法来计算复数的共貌复数(两个实部相等,虚部互为相反教的复数互为共辄复教)。

// 返回当前复数的共辄复数
Complex.prototype.conj = function() { return new Complex(this.r, -this.i); };

JavaScript内置类的原型对象也是一样如此“开放”,也就是说可以给数字、字符串、数组、函数等数据类型添加方法。在下例中我们曾给ECMAScript 3中的函数类添加了bind( )方法,这个方法原来是没有的:
if (!Function.prototype.bind) {
Function.prototype.bind = function(o /*, args */) {
// bind()方法的代码…
};
}

JavaScript内置类的原型对象也是一样如此“开放”,也就是说可以给数字、字符串、数组、函数等数据类型添加方法。在下例中我们曾给ECMAScript 3中的函数类添加了bind( )方法,这个方法原来是没有的:

if (!Function.prototype.bind) {
 Function.prototype.bind = function(o /*, args */) {
     // bind()方法的代码...
 };
}

这里有一些其他的例子:
// 多次调用这个函数传入一个迭代数
// 比如,要输出”hello”三次:
// var n = 3;
// n.times(function(n) { console.log(n + ” hello”); });
Number.prototype.times = function(f, context) {
var n = Number(this);
for(var i = 0; i < n; i++) f.call(context, i);
};

// 如果不存在ES5的String.trim()方法的话,就定义它
// 这个方法用以去除字符串开头和结尾的空格
String.prototype.trim = String.prototype.trim || function() {
if (!this) return this; // 空字符串不做处理
return this.replace(/^\s+|\s+$/g, “”); //使用正则表达式进行空格替换
};

// 返回函数的名字,如果它有(非标准的)name属性,则直接使用name属性
// 否则,将函数转换为字符串然后从中提取名字
// 如果是没有名字的函数,则返回一个空字符串
Function.prototype.getName = function() {
return this.name || this.toString().match(/function\s*([^()*]\(/)[1];
};

可以给Object.prototype添加方法,从而使所有的对象都可以调用这些方法。但这种做法并不推荐,因为在ECMAScript 5之前,无法将这些新增的方法设置为不可枚举的,如果给Object.prototype添加属性,这些属性是可以被for/in循环遍历到的。
然而并不是所有的宿主环境(比如Web浏览器)都可以使用Object.defineProperty(),这跟ECMAScript具体实现有关。比如,在很多Web浏览器中,可以给HTMLElement.prototype添加方法,这样当前文档中表示HTML标记的所有对象就可以继承这些方法。但当前版本的IE则不支持这样做。这对客户端编程实用技术有着严重的限制。

这里有一些其他的例子:

// 多次调用这个函数传入一个迭代数
// 比如,要输出"hello”三次:
// var n = 3;
// n.times(function(n) { console.log(n + " hello"); });
Number.prototype.times = function(f, context) {
    var n = Number(this);
    for(var i = 0; i < n; i++) f.call(context, i);
};

// 如果不存在ES5的String.trim()方法的话,就定义它
// 这个方法用以去除字符串开头和结尾的空格
String.prototype.trim = String.prototype.trim || function() {
    if (!this) return this;	                   // 空字符串不做处理
    return this.replace(/^\s+|\s+$/g, "");     //使用正则表达式进行空格替换
};

// 返回函数的名字,如果它有(非标准的)name属性,则直接使用name属性
// 否则,将函数转换为字符串然后从中提取名字
// 如果是没有名字的函数,则返回一个空字符串
Function.prototype.getName = function() {
    return this.name || this.toString().match(/function\s*([^()*]\(/)[1];
};

可以给Object.prototype添加方法,从而使所有的对象都可以调用这些方法。但这种做法并不推荐,因为在ECMAScript 5之前,无法将这些新增的方法设置为不可枚举的,如果给Object.prototype添加属性,这些属性是可以被for/in循环遍历到的。

然而并不是所有的宿主环境(比如Web浏览器)都可以使用Object.defineProperty(),这跟ECMAScript具体实现有关。比如,在很多Web浏览器中,可以给HTMLElement.prototype添加方法,这样当前文档中表示HTML标记的所有对象就可以继承这些方法。但当前版本的IE则不支持这样做。这对客户端编程实用技术有着严重的限制。

————————

class augmentation

The prototype based inheritance mechanism in JavaScript is dynamic: an object inherits properties from its prototype. If the properties of the prototype change after the object is created, it will also affect all instance objects that inherit the prototype. This means that we can extend JavaScript classes by adding new methods to the prototype object. Here, we add a method to the complex class in the above example to calculate the common complex of the complex (two real parts are equal, the imaginary parts are opposite to each other, and the complex taught by each other is common).
//Returns the common complex of the current complex
Complex.prototype.conj = function() { return new Complex(this.r, -this.i); };

The prototype based inheritance mechanism in JavaScript is dynamic: an object inherits properties from its prototype. If the properties of the prototype change after the object is created, it will also affect all instance objects that inherit the prototype. This means that we can extend JavaScript classes by adding new methods to the prototype object. Here, we add a method to the complex class in the above example to calculate the common complex of the complex (two real parts are equal, the imaginary parts are opposite to each other, and the complex taught by each other is common).

// 返回当前复数的共辄复数
Complex.prototype.conj = function() { return new Complex(this.r, -this.i); };

The prototype object of JavaScript built-in class is also so “open”, that is, you can add methods to data types such as numbers, strings, arrays and functions. In the following example, we added the bind() method to the function class in ECMAScript 3, which was not available before:
if (!Function.prototype.bind) {
Function.prototype.bind = function(o /*, args */) {
//Code for bind() method
};
}

The prototype object of JavaScript built-in class is also so “open”, that is, you can add methods to data types such as numbers, strings, arrays and functions. In the following example, we added the bind() method to the function class in ECMAScript 3, which was not available before:

if (!Function.prototype.bind) {
 Function.prototype.bind = function(o /*, args */) {
     // bind()方法的代码...
 };
}

Here are some other examples:
//Call this function multiple times to pass in an iteration
//For example, to output “hello” three times:
// var n = 3;
// n.times(function(n) { console.log(n + ” hello”); });
Number.prototype.times = function(f, context) {
var n = Number(this);
for(var i = 0; i < n; i++) f.call(context, i);
};
//If the string. Trim () method of Es5 does not exist, define it
//This method removes spaces at the beginning and end of a string
String.prototype.trim = String.prototype.trim || function() {
if (!this) return this; // Empty strings are not processed
Return this. Replace (/ ^ \ S + | \ S + $/ g, “”); / / replace spaces with regular expressions
};
//Returns the name of the function. If it has a (non-standard) name attribute, the name attribute is used directly
//Otherwise, convert the function to a string and extract the name from it
//If it is a function without a name, it returns an empty string
Function.prototype.getName = function() {
return this.name || this.toString().match(/function\s*([^()*]\(/)[1];
};
You can add methods to object.prototype so that all objects can call these methods. However, this method is not recommended because these new methods cannot be set as non enumerable before ECMAScript 5. If you add properties to object.prototype, these properties can be traversed by the for / in loop.
However, not all hosting environments (such as web browsers) can use object. Defineproperty () , this is related to the concrete implementation of ECMAScript. For example, in many web browsers, you can add methods to htmlelement.prototype, so that all objects representing HTML tags in the current document can inherit these methods. However, the current version of ie does not support this. This has serious limitations on the practical technology of client-side programming.

Here are some other examples:

// 多次调用这个函数传入一个迭代数
// 比如,要输出"hello”三次:
// var n = 3;
// n.times(function(n) { console.log(n + " hello"); });
Number.prototype.times = function(f, context) {
    var n = Number(this);
    for(var i = 0; i < n; i++) f.call(context, i);
};

// 如果不存在ES5的String.trim()方法的话,就定义它
// 这个方法用以去除字符串开头和结尾的空格
String.prototype.trim = String.prototype.trim || function() {
    if (!this) return this;	                   // 空字符串不做处理
    return this.replace(/^\s+|\s+$/g, "");     //使用正则表达式进行空格替换
};

// 返回函数的名字,如果它有(非标准的)name属性,则直接使用name属性
// 否则,将函数转换为字符串然后从中提取名字
// 如果是没有名字的函数,则返回一个空字符串
Function.prototype.getName = function() {
    return this.name || this.toString().match(/function\s*([^()*]\(/)[1];
};

You can add methods to object.prototype so that all objects can call these methods. However, this method is not recommended, because before ECMAScript 5, these new methods cannot be set as non enumerable. If you add attributes to object.prototype, these attributes can be traversed by the for / in loop.

However, not all hosting environments (such as web browsers) can use object. Defineproperty (), which is related to the specific implementation of ECMAScript. For example, in many web browsers, you can add methods to htmlelement.prototype so that all objects representing HTML tags in the current document can inherit these methods. However, the current version of ie does not support this. This has serious limitations on the practical technology of client programming.