I want to write a JS library and handle it like this:
var c1 = Module.Class();
c1.init();
var c1 = Module.Class();
c2.init();
And of course, c1 and c2 can not share the same variables.
I think I know how to do this with objects, it would be:
var Module = {
Class = {
init = function(){
...
}
}
}
But the problem is I can't have multiple instances of Class if I write in this way.
So I'm trying to achieve the same with function, but I don't think I'm doing it right.
(function() {
var Module;
window.Module = Module = {};
function Class( i ) {
//How can "this" refer to Class instead of Module?
this.initial = i;
}
Class.prototype.execute = function() {
...
}
//Public
Module.Class = Class;
})();
I don't have a clue if it's even possible, but I accept suggestions of other way to create this module.
I don't know if it's relevant also, but I'm using jQuery inside this library.
Usage:
var c1 = Module.Class("c");
var c2 = Module.Class("a");
var n = c1.initial(); // equals 'c'
c1.initial("s");
n = c1.initial(); // equals 's'
Module Code:
(function(window) {
var Module = window.Module = {};
var Class = Module.Class = function(initial)
{
return new Module.Class.fn.init(initial);
};
Class.fn = Class.prototype = {
init: function(initial) {
this._initial = initial;
},
initial: function(v){
if (v !== undefined) {
this._initial = v;
return this;
}
return this._initial;
}
};
Class.fn.init.prototype = Class.fn;
})(window || this);
This is using the JavaScript "Module" Design Pattern; which is the same design pattern used by JavaScript libraries such as jQuery.
Here's a nice tutorial on the "Module" pattern:
JavaScript Module Pattern: In-Depth
Related
I am studying Babel recently, and I followed the steps I found in GitHub, everything goes on the right way, I wrote some arrow function, and I get the right result, but when I tried to create class, some problems occurred, I don't know how to handle it.
problem picture
I was informed that the "unresolved function or method require()"
Does it mean I forgot to do something, First I thought maybe I need load requirejs.js, but it did work too, I search the question, but I can't find the solution, so is there someone can help me?
my code is
const square = n => n * n;
var a = 2000;
class SSPageController{
showPage(){
}
}
and the result code is
"use strict";
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require("babel-runtime/helpers/createClass");
var _createClass3 = _interopRequireDefault(_createClass2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var square = function square(n) {
return n * n;
};
var a = 2000;
var SSPageController = function () {
function SSPageController() {
(0, _classCallCheck3.default)(this, SSPageController);
}
(0, _createClass3.default)(SSPageController, [{
key: "showPage",
value: function showPage() {}
}]);
return SSPageController;
}();
i wonder to know is the code below runs right
a.js:
var obj = {
name: 'a'
};
module.exports = obj;
b.js
var b = require('./a');
module.exports = b;
c.js
var a = require('./a');
console.log(a); // {name: 'a'}
a.name = 'b';
console.log(require('./a')); // {name: 'b'}
console.log(require('./b')); // {name: 'b'}
so, i can change a module exports from outside
if i cange the a.js to a.json
a.json
{
"name": "a"
}
i got the same result
how can i export a module can't modify or override form outside
You can freeze an object:
// in order for people to not add properties through the prototype
var o = Object.create(null);
o.name = 'a';
Object.freeze(o); // no one can change properties
Object.seal(o); // no one can add properties;
module.exports = o;
If you're using a modern version of nodejs (read io.js) you can also use a proxy:
var o = {name: 'a'};
var p = new Proxy(o, {
set: function(obj, prop, value) {
// unlike the freeze approach, this also throws in loose mode
throw new TypeError("Can't set anything on this object");
}
});
return p;
That said, who are you guarding against? Why would people change the object in another module?
Here is my code:
var handleCondition = function(condition,params){
var dup_condition;
dup_condition = condition;
var isArray = function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
var __replace = function(str){
var reg_slot = /^#(.+)/;
if(reg_slot.test(str) == true){
var ss = reg_slot.exec(str)[1];
return params[ss];
}else{
return str;
}
};
var compare = function(a){
var arr = a;
if(params != undefined){
for(var j =1;j<arr.length;j++){
arr[j] = __replace(arr[j]);
}
}
switch(arr[0]){
case "$eq":
case "==":
return (arr[1] == arr[2]);
default:
return (arr[1] == arr[2]);
}
};
if(isArray(dup_condition)){
var im = function (arr){
for(var i=0;i<3;i++){
if(isArray(arr[i])){
arr[i] = im(arr[i]);
}
}
return compare(arr);
};
var res = im(dup_condition);
return res;
}
};
/*Here are test data*/
var c = {
"beforeDNS":
["$eq","#host",["$eq",10,10]]
,
"afterDNS":["$match",/^10\.+/,"#ip"]
};
var params ={
host:"dd"
};
console.log(c["beforeDNS"]); // ==> ["$eq","#host",["$eq",10,10]]
handleCondition(c["beforeDNS"],params);
console.log(c["beforeDNS"]); // ==> ["$eq","dd",true]
handleCondition(c["beforeDNS"],params);
The first time I run the code with the expected result;
However , when I tried to run the function second time,to my surprise,the value of c["beforeDNS"] has changed unexpectedly!
In fact,I haven't write any code in my function to modify the value of this global variable,but it just changed.
So please help me find the reason of this mysterious result or just fix it.Thanks!
Your dup_condition variable isn't duping anything. It's just a reference to the argument you pass in.
Thus when you pass it to the im function, which modifies its argument in place, it is just referencing and modifying condition (which is itself a reference to the c["beforeDNS"] defined outside the function).
To fix this you might use slice or some more sophisticated method to actually dupe the arguments. slice, for example, would return a new array. Note though that this is only a shallow copy. References within that array would still refer to the same objects.
For example:
if (isArray(condition)) {
var dup_condition = condition.slice();
// ...
}
In javascript the objects are passed by reference. In other words, in handleCondition dup_condition still points to the same array. So, if you change it there you are actually changing the passed object. Here is a short example which illustrates the same thing:
var globalData = {
arr: [10, 20]
};
var handleData = function(data) {
var privateData = data;
privateData.arr.shift();
privateData.arr.push(30);
}
console.log(globalData.arr);
handleData(globalData);
console.log(globalData.arr);
The result of the script is:
[10, 20]
[20, 30]
http://jsfiddle.net/3BK4b/
I suddenly realized that event emitter in NodeJS is usually like a static method in Java.. Example:
// This illustrated that event listener is universal
function A(a){
var that = this;
this.a = a;
this.cnt = 0;
this.done = function(){
this.emit("done");
};
this.say = function(){
console.log(a + " = " + that.cnt);
};
this.inc = function(){
that.cnt++;
};
}
A.prototype = new events.EventEmitter;
var a = new A("a"),
b = new A("b"),
c = new A("c");
a.on("done",function(){a.inc()});
b.on("done",function(){b.inc()});
c.on("done",function(){c.inc()});
c.done();
c.done();
a.say();
b.say();
This code would give output:
a = 2
b = 2
While I'm actually expecting:
a = 0
b = 0
I believe this is because of the line:
A.prototype = new events.EventEmitter;
and I think the "prototype" kind of definition would be used like "static" in Java.
In order to have per-object based event listener, I changed the above code to be:
function B(a){
var that = this;
this.evt = new events.EventEmitter;
this.a = a;
this.cnt = 0;
this.done = function(){
this.evt.emit("done");
};
this.say = function(){
console.log(a + " = " + that.cnt);
};
this.inc = function(){
that.cnt++;
};
}
var a = new B("a"),
b = new B("b"),
c = new B("c");
a.evt.on("done",function(){a.inc()});
b.evt.on("done",function(){b.inc()});
c.evt.on("done",function(){c.inc()});
c.done();
c.done();
a.say();
b.say();
This would be per-object event listener, but I don't really think that is a good design/implementation because it breaks the chaining of EventEmitter. I.e., like code bellow:
// can chain another method of A after the on() method
a.on("event",functionCallback).anotherMethodOfA();
I'd like to ask, what's a proper implementation of the per-object event listener in NodeJS?
You can use addListener or on to attach listeners to your custom events. You won't need to chain calls on these methods. Of course you can inherit any object from EventEmitter and add emitting functionality to your object. You can inherit your object from an instance of EventEmitter. There's is function called inherit in the util library which does that for you.
var util = require('util');
var eventEmitter = require('events').EventEmitter;
// Now create your constructor/object.
function MyObj(a, b) {
this.a = a;
this.b = b;
.
.
.
}
util.inherits(MyObj,eventEmitter);
// Implement your methods and add the functionality you need.
MyObj.prototype.aMethod = function(arg) {
.
.
.
// Define how to emit events
if (arg == 'A')
this.emit('eventA', this.a);
else if (arg == 'B')
this.emit('eventB');
// Return this for chaining method calls
return this;
}
MyObj.prototype.anotherMethod = function() {
// Add more functionality...
.
.
.
return this;
}
// Now instantiate the constructor and add listenters
var instanceOfMyObj = new MyObj('a parameter', 'another parameter');
instanceOfMyObj.on('eventA', function(a){
// Handle the event
});
// Now chain calls..
instanceOfMyObj.aMethod('A').anotherMethod(); // This will trigger eventA...
I am trying to implement generators in Node.js. I came across node-fiber and node-lazy. Node-lazy deals with arrays and streams, but does not generate lazy things inherently (except numbers).
While using fiber looks cleaner, it has its cons, and as such, I prefer pure Javascript with closures as it's more explicit. My question is: are there memory or perf problems using closure to generate an iterator?
As an example, I'm trying to iterate through a tree depth-first, for as long as the caller asks for it. I want to find 'waldo' and stop at the first instance.
Fiber:
var depthFirst = Fiber(function iterate(tree) {
tree.children.forEach(iterate);
Fiber.yield(tree.value);
});
var tree = ...;
depthFirst.run(tree);
while (true) {
if (depthFirst.run() === 'waldo')
console.log('Found waldo');
}
Pure JavaScript with closures:
function iterate(tree) {
var childIndex = 0;
var childIter = null;
var returned = false;
return function() {
if (!childIter && childIndex < tree.children.length)
childIter = iterate(tree.children[childIndex++]);
var result = null;
if (childIter && (result = childIter()))
return result;
if (!returned) {
returned = true;
return tree.value;
}
};
}
var tree = ...;
var iter = iterate(tree);
while (true) {
if (iter() === 'waldo')
console.log('found waldo');
}