除了模仿经典类系统,JavaScript原型系统还能做什么?
原型系统看起来比传统课堂系统灵活得多,但人们似乎对模仿传统课堂系统的所谓“最佳实践”感到满意:除了模仿经典类系统,JavaScript原型系统还能做什么?,javascript,prototype,prototype-programming,Javascript,Prototype,Prototype Programming,原型系统看起来比传统课堂系统灵活得多,但人们似乎对模仿传统课堂系统的所谓“最佳实践”感到满意: function foo() { // define instance properties here } foo.prototype.method = //define instance method here new foo() 一个原型系统必须具备所有的灵活性才能做其他事情 除了模仿类之外,原型系统还有什么用途吗?原型可以做什么样的事情?哪些类不能做,哪些类没有?原型系统通过标准对象实
function foo() {
// define instance properties here
}
foo.prototype.method = //define instance method here
new foo()
一个原型系统必须具备所有的灵活性才能做其他事情
除了模仿类之外,原型系统还有什么用途吗?原型可以做什么样的事情?哪些类不能做,哪些类没有?原型系统通过标准对象实现继承,提供了一个迷人的模型。当然,这主要用于表示已建立的简单的实例类概念,但没有类作为需要特定语法来创建它们的语言级不可变结构。通过使用普通对象,您现在可以对“类”执行的所有操作(您也可以执行所有操作)——这就是您所说的灵活性 然后,这种灵活性被大量用于以编程方式扩展和更改类,仅使用JavaScript的给定对象变异功能:
- 多重遗传的融合子和性状
- 在实例化从原型继承的对象之后,可以修改原型
- 高阶函数和方法装饰器可以轻松地用于原型的创建
当然,原型模型本身比仅仅实现类更强大。这些特性很少使用,因为类的概念非常有用且广泛,所以原型继承的实际功能并不广为人知(在JS引擎中也没有得到很好的优化:-/)
- 关闭现有对象的原型可以极大地改变它们的行为。(随附全面支持)
- 一些软件工程模式可以直接用对象实现。例如具有属性的,a包括动态链,哦,当然还有
最后一个例子是带有默认值的选项对象。每个人都使用
但更具活力的方法是使用var myOptions = extend({}, defaultOptions, optionArgument);
var myOptions = extend(Object.create(defaultOptions), optionArgument);
- 我认为原型继承系统允许更动态地添加方法/属性
您可以轻松地扩展其他人编写的类,例如所有jQuery插件,还可以轻松地添加到本机类中,向字符串、数组和任何对象添加实用函数
例如:
也可以从其他类复制方法
function myString(){
this[0] = '42';
}
myString.prototype = String.prototype;
foo = new myString();
foo.first() // == '42'
这还意味着您可以在从原型继承对象后扩展原型,但这些更改将被应用
而且,就我个人而言,我发现原型非常方便和简单,在对象中布局方法对我来说非常有吸引力;) 2013年6月,我回答了一个关于。从那以后,我花了很多时间思考继承问题,包括原型继承和古典继承,并且我写了大量关于继承的文章 是的,原型继承的主要用途是模拟类。然而,它的用途远不止是模拟类。例如,原型链与范围链非常相似
var foo = {};
var bar = Object.create(foo);
var baz = Object.create(bar);
// chain: baz -> bar -> foo -> Object.prototype -> null
function foo() {
function bar() {
function baz() {
// chain: baz -> bar -> foo -> global
}
}
}
原型范围同构
JavaScript中的原型和作用域有很多共同点。JavaScript中有三种常见的链类型:
var foo = {};
var bar = Object.create(foo);
var baz = Object.create(bar);
// chain: baz -> bar -> foo -> Object.prototype -> null
function foo() {
function bar() {
function baz() {
// chain: baz -> bar -> foo -> global
}
}
}
var foo = {};
var bar = Object.create(foo);
var baz = Object.create(bar);
// chain: baz -> bar -> foo -> Object.prototype -> null
function foo() {
function bar() {
function baz() {
// chain: baz -> bar -> foo -> global
}
}
}
var chain = {
foo: function () {
return this;
},
bar: function () {
return this;
},
baz: function () {
return this;
}
};
chain.foo().bar().baz();
function foo() {
var bar = {};
var baz = Object.create(bar);
with (baz) {
// chain: baz -> bar -> Object.prototype -> foo -> global
}
}
那么原型范围同构有什么用呢?一个直接用途是使用原型链对作用域链建模。这正是我为自己的编程语言所做的,我用JavaScript实现了它
我首先定义了Bianca的全局范围,在一个文件中填充了一堆有用的数学函数,文件名如下:
var global = module.exports = Object.create(null);
global.abs = new Native(Math.abs);
global.acos = new Native(Math.acos);
global.asin = new Native(Math.asin);
global.atan = new Native(Math.atan);
global.ceil = new Native(Math.ceil);
global.cos = new Native(Math.cos);
global.exp = new Native(Math.exp);
global.floor = new Native(Math.floor);
global.log = new Native(Math.log);
global.max = new Native(Math.max);
global.min = new Native(Math.min);
global.pow = new Native(Math.pow);
global.round = new Native(Math.round);
global.sin = new Native(Math.sin);
global.sqrt = new Native(Math.sqrt);
global.tan = new Native(Math.tan);
global.max.rest = { type: "number" };
global.min.rest = { type: "number" };
global.sizeof = {
result: { type: "number" },
type: "function",
funct: sizeof,
params: [{
type: "array",
dimensions: []
}]
};
function Native(funct) {
this.funct = funct;
this.type = "function";
var length = funct.length;
var params = this.params = [];
this.result = { type: "number" };
while (length--) params.push({ type: "number" });
}
function sizeof(array) {
return array.length;
}
注意,我使用Object.create(null)
创建了全局范围。我这样做是因为全局作用域没有任何父作用域
之后,我为每个程序创建了一个单独的程序范围,其中包含程序的顶级定义。代码存储在一个名为的文件中,该文件太大,无法容纳一个答案。以下是文件的前三行:
var parse = require("./ast");
var global = require("./global");
var program = Object.create(global);
如您所见,全局范围是程序范围的父级。因此,程序
继承自全局
,使范围变量查找与对象属性查找一样简单。这使得语言的运行时更加简单
程序范围包含程序的顶级定义。例如,考虑下面的矩阵乘法程序,它存储在文件:
顶级定义是列
、行
和添加
。这些函数中的每一个都有自己的函数作用域,它继承自程序作用域。可在以下网站上找到该代码:
例如,add
的功能范围具有矩阵a
和b
的定义
因此,除了类之外,原型对于函数范围的建模也很有用
代数数据类型建模的原型
类不是唯一可用的抽象类型。在函数式编程语言中,数据建模使用
代数数据类型的最佳示例是列表:
数据列表a=Nil | Cons a(列表a)
该数据定义仅意味着a的列表可以是空列表(即Nil
),也可以是插入a的列表中的类型为“a”的值(即Cons a(列表a)
)。例如,以下是所有列表:
Nil::列表a
Cons 1 Nil::列表编号
Cons 1(Cons 2无)::列表编号
欺骗