属性查找贯穿原型链,与动态范围非常匹配。只需传递您自己的动态范围变量环境即可使用,而不是使用Javascript的词法作用域。
// Polyfill for older browsers. Newer ones already have Object.create.if (!Object.create) { // You don't need to understand this, but Object.create = function(proto) { // this constructor does nothing, function cons() {} // and we assign it a prototype, cons.prototype = proto; // so that the new object has the given proto without any side-effects. return new cons(); };}
// Define a new classfunction dyn() {}// with a method which returns a copy-on-write clone of the object.dyn.prototype.cow = function() { // An empty object is created with this object as its prototype. Javascript // will follow the prototype chain to read an attribute, but set new values // on the new object. return Object.create(this);}
// Given an environment, read x then write to it.function g(env) { console.log(env.x); env.x = 2;}// Given an environment, write x then call f with a clone.function f(env) { env.x = 3; g(env.cow());}
// Create a new environment.var env = new dyn();// env -> {__proto__: dyn.prototype}// Set a value in it.env.x = 1;// env -> {x: 1} // Still has dyn.prototype, but it's long so I'll leave it out.f(env.cow());// f():// env -> {__proto__: {x: 1}} // Called with env = caller's env.cow()// > env.x = 3// env -> {x: 3, __proto__: {x: 1}} // New value is set in current object// g():// env -> {__proto__: {x: 3, __proto__: {x: 1}}} // caller's env.cow()// env.x -> 3 // attribute lookup follows chain of prototypes// > env.x = 2// env -> {x: 2, __proto__: {x: 3, __proto__: {x: 1}}}console.log(env.x);// env -> {x: 1} // still unchanged!// env.x -> 1
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)