implementation of dependency injection like angular - javascript

i have recently an interview and the interviewer simply ask me one question and he say me take your time the question is "can you implement dependency injection like angular good program?" i try to do my best but it seem the interview don't like my program so can anyone give me a simple advice how can i implement it like angular?
Thanks

var WelcomeController = function (Greeter) {
document.write(Greeter.greet());
};
var Injector = {
dependencies: {},
process: function(target) {
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var text = target.toString();
var args = text.match(FN_ARGS)[1].split(',');
target.apply(target, this.getDependencies(args));
},
getDependencies: function(arr) {
var self = this;
return arr.map(function(value) {
return self.dependencies[value];
});
},
register: function(name, dependency) {
this.dependencies[name] = dependency;
}
};
var RobotGreeter = {
greet: function() {
return 'Domo Arigato';
}
};
var OtherGreeter = {
greet: function() {
return 'That will do pig.';
}
};
// Randomly register a different greeter to show that WelcomeController is truly dynamic.
Injector.register('Greeter', Math.random() > 0.5 ? RobotGreeter : OtherGreeter);
Injector.process(WelcomeController);

Related

JavaScript: Prevent Array.push()

I have a sealed object with an array member on which I want to prevent direct pushes.
var myModule = (function () {
"use strict";
var a = (function () {
var _b = {},
_c = _c = "",
_d = [];
Object.defineProperty(_b, "c", {
get: function () { return _c; }
});
Object.defineProperty(_b, "d", {
get { return _d; }
});
_b.addD = function (newD) {
_d.push(newD);
};
Object.seal(_b);
return _b;
}());
var _something = { B: _b };
return {
Something: _something,
AddD: _b.addD
};
}());
myModule.Something.c = "blah"; // doesn't update = WIN!!
myModule.AddD({}); // pushed = WIN!
myModule.Something.d.push({}); // pushed = sadness
How can I prevent the push?
UPDATE:
Thanks for all the thoughts. I eventually need the JSON to send to the server. It looks like I might need to use an object for the array then figure out a way to generate and return the JSON needed, or change _something to use .slice(). Will play and report.
you could override the push method:
var _d = [];
_d.__proto__.push = function() { return this.length; }
and when you need to use it in your module, call Array.prototype.push:
_b.addD = function (newD) {
Array.prototype.push.call(_d, newD);
};
I haven't done any performance tests on this, but this certainly helps to protect your array.
(function(undefined) {
var protectedArrays = [];
protectArray = function protectArray(arr) {
protectedArrays.push(arr);
return getPrivateUpdater(arr);
}
var isProtected = function(arr) {
return protectedArrays.indexOf(arr)>-1;
}
var getPrivateUpdater = function(arr) {
var ret = {};
Object.keys(funcBackups).forEach(function(funcName) {
ret[funcName] = funcBackups[funcName].bind(arr);
});
return ret;
}
var returnsNewArray = ['Array.prototype.splice'];
var returnsOriginalArray = ['Array.prototype.fill','Array.prototype.reverse','Array.prototype.copyWithin','Array.prototype.sort'];
var returnsLength = ['Array.prototype.push','Array.prototype.unshift'];
var returnsValue = ['Array.prototype.shift','Array.prototype.pop'];
var funcBackups = {};
overwriteFuncs(returnsNewArray, function() { return []; });
overwriteFuncs(returnsOriginalArray, function() { return this; });
overwriteFuncs(returnsLength, function() { return this.length; });
overwriteFuncs(returnsValue, function() { return undefined; });
function overwriteFuncs(funcs, ret) {
for(var i=0,c=funcs.length;i<c;i++)
{
var func = funcs[i];
var funcParts = func.split('.');
var obj = window;
for(var j=0,l=funcParts.length;j<l;j++)
{
(function() {
var part = funcParts[j];
if(j!=l-1) obj = obj[part];
else if(typeof obj[part] === "function")
{
var funcBk = obj[part];
funcBackups[funcBk.name] = funcBk;
obj[part] = renameFunction(funcBk.name, function() {
if(isProtected(this)) return ret.apply(this, arguments);
else return funcBk.apply(this,arguments);
});
}
})();
}
}
}
function renameFunction(name, fn) {
return (new Function("return function (call) { return function " + name +
" () { return call(this, arguments) }; };")())(Function.apply.bind(fn));
};
})();
You would use it like so:
var myArr = [];
var myArrInterface = protectArray(myArr);
myArr.push(5); //Doesn't work, but returns length as expected
myArrInterface.push(5); //Works as normal
This way, you can internally keep a copy of the interface that isn't made global to allow your helper funcs to modify the array as normal, but any attempt to use .push .splice etc will fail, either directly, or using the .bind(myArr,arg) method.
It's still not completely watertight, but a pretty good protector. You could potentially use the Object.defineProperty method to generate protected properties for the first 900 indexes, but I'm not sure of the implications of this. There is also the method Object.preventExtensions() but I'm unaware of a way to undo this effect when you need to change it yourself
Thank you, dandavis!
I used the slice method:
var myModule = (function () {
"use strict";
var a = (function () {
var _b = {},
_c = _c = "",
_d = [];
Object.defineProperty(_b, "c", {
get: function () { return _c; }
});
Object.defineProperty(_b, "d", {
get { return _d.slice(); } // UPDATED
});
_b.updateC = function (newValue) {
_c = newValue;
};
_b.addD = function (newD) {
_d.push(newD);
};
Object.seal(_b);
return _b;
}());
var _something = { B: _b };
return {
Something: _something,
AddD: _b.addD
};
}());
myModule.Something.c = "blah"; // doesn't update = WIN!!
myModule.AddD({}); // pushed = WIN!
myModule.Something.d.push({}); // no more update = happiness
This allows me to protect from direct push calls enforcing some logic.

JS module pattern override function

I have following pattern
BASE = function () {
var that = {};
var number = 10;
that.showNumber = function(){
that.alertNumber();
}
that.alertNumber = function () {
alert(number);
};
return that;
};
CHILD = function () {
var that = Object.create(BASE());
var secondNumber = 20;
// Override base function
that.alertNumber = function () {
alert(secondNumber);
};
return that;
};
var ch = CHILD();
ch.showNumber();
Can you tell me how can I adjust my module pattern inspired by Douglas CrockFord to fully override alerNumber function? So far showNumber function displays 10 instead of 20.
Thank you all in advanced
JSFiddle with code is here
You could change
that.showNumber = function(){
that.alertNumber();
}
to
that.showNumber = function(){
this.alertNumber();
}
But I'm not sure I see why you don't simply use the prototype-base inheritance model.

JavaScript Constants

we know we can protect the value of variables , so user can't change the value of variables the existing!! Does implementation this have nothing wrong with object..??
for example..
const x = 5;
x = 10;
alert(x)
// will be returned 5
using an object..
const obj = {
init: function() {
obj.show()
},
show: function() {
//..
},
hide: function() {
//..
}
}
obj.init();
If you can get away with using JS5, you have this option:
var CONST = {
NAME: "The Cool Gizmo",
VERSION: 2
};
Object.freeze(CONST);
alert(CONST.NAME);
var myObj = (function () {
var privVar1 = 111,
privVar2 = 222;
var getConstants = function () {
return { priv1: privVar1, priv2: privVar2 }
};
return { getConstants: getConstants };
})();
myObj.getConstants().priv1
The const keyword is not currently supported by all browsers, nor is it a part of the official Javascript specification in use today. (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/const)
To accomplish a constant, consider encapsulating the behavior you need in a function:
var getConstant = function(key) {
var constants = { x: 5 };
return constants[key];
};
alert(getConstant("x"));
Or, simply use a variable with the appropriate scope to protect 3rd parties from setting its value:
function myModule() {
var x = 5;
doSomethingWith(x);
}

Prototypal Namespacing

I have a Constructor function "Animals", that is namespacing some other Constructor functions, "Crocodile" and "Monkey":
var Monkey = function(Animals) {
this.Animals = Animals;
};
Monkey.prototype.feedMe = function() {
this.Animals.feed();
};
var Crocodile = function(Animals) {
this.Animals = Animals;
};
Crocodile.prototype.feedMe = function() {
this.Animals.feed();
};
var Animals = function(zoo) {
this.zoo = zoo;
};
Animals.prototype.feed = function() {
//feed the animal
};
Animals.prototype.Monkey = function() {
this.Animals = Animals.prototype;
};
Animals.prototype.Monkey.prototype = Monkey.prototype;
Animals.prototype.Crocodile = function() {
this.Animals = Animals.prototype;
};
Animals.prototype.Crocodile.prototype = Crocodile.prototype;
With the intention that I should be able to do the following:
var animals = new Animals("NY");
var monkey = new animals.Monkey();
monkey.feed();
I'm receiving an error that says that monkey.feed() is not a function. I'm assuming i'm doing something wrong with the way i'm inheriting the Monkey function inside the Animal constructor function but for the life of me I haven't been able to find the solution.
What is the correct method I should be using to namespace these functions?
I have seen quite some stuff, but abusing prototypes for namespaces, what the heck. What's wrong with a nice and simple:
var Animals = {
Crocodile: {
}
}
Or if you want the constructor way:
var Animals = function () {
return {
Crocodile: function () {}
}
};
var a = new Animals();
var c = new a.Crocodile();

How can i simply achieve Sencha-Like class inheritance in Backbone?

I'm starting a new Backbone app, and I've been quite fond of the javascript class inheritance system of Sencha Touch 2.0, basically i want to be able to do this :
Helium.define('Application', {
namespace: 'Helium',
constructor: function() {
console.warn('Helium');
}
});
Helium.define('Application', {
namespace: 'MyApp',
extend: 'Backbone.Events',
routers: ['Cards'],
constructor: function() {
console.warn(this);
this.callParent();
console.warn('MyApp');
//console.warn(Helium.getDisplayName(arguments.callee));
}
});
I'm stuck on the prototype chain definition (to make the this.callParent() work) :
var p = Object.create(extend);
var o = _.extend(p, data);
/*function() {
var _o = _.extend(p, data);
_o.constructor.apply(o, arguments);
return _o;
};*/
o.prototype.superclass = p;
o.prototype.callParent = function() {
console.warn(p);
};
Here is the complete micro-implementation so far :
So far, i have done this :
_.mixin({
resolve : function(path, base, separator) {
var parts = path.split('.' || separator),
key = parts.pop();
base = base || window;
while (parts.length) {
part = parts.shift();
base = base[part] = base[part] || {};
}
base[key] = base[key] || {};
return base[key];
}});
Helium = {
define: function(className, data) {
var base = window,
extend = data.extend || {constructor : function() {}},
namespace = data.namespace || null;
if(namespace) {
window[namespace] = window[namespace] || {};
base = window[namespace];
}
if(_.isString(extend)) extend = _.resolve(extend);
if(!extend) throw 'Extend error';
var parts = className.split('.'),
key = parts.pop();
while (parts.length) {
part = parts.shift();
base = base[part] = base[part] || {};
}
delete data.extend;
//delete data.namespace;
data.$name = key;
data.$className = className;
var p = Object.create(extend);
var o = _.extend(p, data);
/*function() {
var _o = _.extend(p, data);
_o.constructor.apply(o, arguments);
return _o;
};*/
o.prototype.superclass = p;
o.prototype.callParent = function() {
console.warn(p);
};
},
getDisplayName: function(callee) {
console.warn('getDisplayName', [this, arguments]);
console.warn(callee.toString());
}
};
I see what you're going for here but if your end game is really being able to call the parent constructor I think it's a little convoluted to try and impose Sencha's inheritance model on Backbone because it is so simple and lightweight and ultimately it has its own inheritance implementation.
Since Backbone's extend() only exists on Backbone classes I think this is a good resource. Unless I'm misunderstanding you I think something along the lines of MyApp.__super__.initialize() in Backbone would be roughly equivalent to this.callParent() in Sencha Touch.

Categories