I'm trying to implement native bind functionality. However, when I try to test it out, I'm not getting the expected output.
Can someone tell me where am I going wrong?
Function.prototype.myBind = function(...args) {
const self = this;
return function() {
return self.apply(this, args);
}
};
function demo() {
return {
name: 'James Bond',
printName: function (args) {
console.log(this.name, args);
}
};
}
const test = {
name: 'Aqua Man'
};
console.log(demo().printName.myBind(test)('2020'));
// expected
console.log(demo().printName.bind(test)('2020'));
You need to bind to argument like this:
Function.prototype.myBind = function(binder) {
const self = this;
return function() {
return self.apply(binder, arguments);
}
};
Related
If I have
var test = {
return {
foo: function() {
return 1
},
sub: {
bar: function() {
var foo = this.foo() // <--- here, does obviously not work
}
}
}
}
What is the recommended and best way to access foo() from within sub.bar() ...?
To clarify, I want to split an angularjs service into sections.
"Real" code:
angular.module('myApp').factory('Service' function() {
return {
foo: function() {
return 1
},
sub: {
bar: function() {
var foo = this.foo() // <--- here, does obviously not work
}
}
}
})
Since you are using an angular factory, you can Use the Revealing Module Pattern:
angular.module('myApp').factory('Service' function() {
function foo() {
return 1
}
var sub = {
bar: function() {
var foo = foo()
}
}
return {
foo: foo,
sub: sub
}
})
This is not ok:
return {
foo: function() {
return 1
}
}
You need to remove that return statement and within the function bar you can access the function foo using the name of the variable test as follow: test.foo()
var test = {
foo: function() {
return 98989;
},
sub: {
bar: function() {
var foo = test.foo();
console.log(foo);
}
}
};
test.sub.bar();
Another way is using the function bind, but it's overkill:
var test = {
foo: function() {
return 98989;
},
sub: {
bar: function() {
var foo = this.foo(); // Using the object 'this'
console.log(foo);
}
}
};
test.sub.bar.bind(test)();
Now, you can declare a variable service and use that variable:
angular.module('myApp').factory('Service'function() {
var service = {
foo: function() {
return 1
},
sub: {
bar: function() {
var foo = service.foo();
^^^^^^^
}
}
};
return service;
});
This question already has answers here:
Methods in ES6 objects: using arrow functions
(6 answers)
Closed 4 years ago.
When using the module pattern in ES5, calling this.methodName gives me the methodName in the return object. But in ES6 it's a little bit different now....
The old way (with ES5):
var moduleOld = (function() {
//private
var privateArray = [1,2,3,4];
return {
getItemCount: function() {
return privateArray.length;
},
getTotal: function() {
return this.getItemCount();
}
};
})();
//output
console.log(moduleOld.getTotal()); //4 <-- Now, I want the same results with ES6 syntax
The new way (with ES6):
let moduleES6 = (()=> {
//private
let privateArray = [1,2,3,4];
return {
getItemCount: ()=> {
return privateArray.length;
},
getTotal: ()=> {
return this.getItemCount();
}
};
})();
//output
console.log("es6 ", moduleES6.getTotal()); //Uncaught TypeError: this.getItemCount is not a function
There are ways around it...
let moduleES6_2 = (()=> {
//private
let privateArray = [1,2,3,4];
return {
getItemCount: ()=> {
return privateArray.length;
},
getTotal: ()=> {
return moduleES6_2.getItemCount(); // I changed "this" to the module name, i.e. moduleES6_2
}
};
})();
//output
console.log("es6 calling by module name: ", moduleES6_2.getTotal()); //works! But what if I change the module's name? Then I have to also change the function call in the getTotal function.
This way, changing the module's name shouldn't be much of an issue:
let moduleES6_3 = (()=> {
//private
let privateArray = [1,2,3,4];
function getItemCount() {
return privateArray.length;
}
return {
//getItemCount: getItemCount,
getTotal: ()=> {
return getItemCount(); // I am calling the private method. Not the public method!
}
};
})();
//output
console.log("es6 by private method: ", moduleES6_3.getTotal()); //works! But I don't really use the method in the return object, but rather the private declared method.
How do I accesss a "public" function in the return object (module pattern) with ES6?
let moduleES6 = (()=> {
//private
let privateArray = [1,2,3,4];
function getItemCount() {
return privateArray.length;
}
return {
getItemCount: ()=> {
return privateArray.length;
},
getTotal: ()=> {
return this.getItemCount();//<-- how to access the public getItemCount method?
}
};
})();
You can use the shorthand syntax for object methods like getItemCount():
let moduleES6 = (()=> {
//private
let privateArray = [1,2,3,4];
return {
getItemCount() {
return privateArray.length;
},
getTotal() {
return this.getItemCount();
}
};
})();
moduleES6.getTotal() //4
When I'm declaring instance methods in JS I often use this syntax:
var MyObj = function (p1) {
this.p1 = p1;
};
MyObj.prototype = {
method1: function() {},
method2: function() {},
method2: function() {}
};
Is there a similar way to declare "static" methods instead of doing this:
MyObj.static1 = function() {
};
MyObj.static2 = function() {
};
MyObj.static3 = function() {
};
The only thing I can think of is doing it in two steps:
var staticMethods = {
static1: function () {
},
static2: function () {
},
static3: function () {
}
};
Then use this function
function registerStaticMethods(aClass, staticMethods) {
for (var methodName in staticMethods) {
aClass[methodName] = staticMethods[methodName];
}
}
You would use it like this
registerStaticMethods(MyObj, staticMethods);
Sometimes in JavaScript I need many constructors and objects for pseudo-classes because I like objective very much so I do something like:
var anyClass = (function (settings) {
var staticPrivate = {}, staticPublic = function () {
var public = this, private = {};
(function constructor (here, the, args) {
this.hta = [here, the, args, arguments];
}).apply(this, arguments);
arguments = undefined;delete arguments;
private.stuff = function () {}
Object.defineProperties(public, {
"e.g. length": {
get: function () {
return private.length;
},
set: function (newValue) {
return;
},
enumerable: false
}
});
};
Object.defineProperties(staticPublic, {
"staticFinalHiddenString": {
get: function () {
return "YEAH, I'm static and final and hidden...";
},
set: function (newValue) {
return "You cannot set me.. :P";
},
enumerable: false
}
});
staticPrivate.some = function (init) {
if (settings.some == "settings") init();
}
window.requestAnimationFrame(function () {
staticPrivate.some(function (I) {
run(on, first, render);
});
});
return staticPublic;
})({
some: "settings",
here: null
});
And that every time, so now I want a constructor that creates a new class for me. I think on this:
new Class({
constructor: function (here) {
is(my + constructor);
},
properties: {
name: {
getter: function () {},
setter: function (newValue) {},
hidden: false,
static: false,
final: false
},
version: {
getter: function () {
return 0.3;
},
setter: function (newValue) {},
hidden: true,
static: true,
final: true
}
}
});
but my problem is that I have no idea how to create an prototype/constructor with an constructor class.prototype.prototype does not work.
I just tried that:
var Class = (function () {
var Class = (function () {
var constructor = function () {
return (function (information) {
this.prototype = {};
var properties = {};
for(var key in information.properties) {
properties[key] = {
get: information.properties[key].getter,
set: information.properties[key].setter,
enumerable: !information.properties[key].hidden || true
};
};
Object.defineProperties(this.prototype, properties);
return this;
}).apply(this, arguments);
};
return constructor;
})();
return Class;
})();
That does not work for me :C
I hope you can help me. Thanks...
I understood my mistake and now I can return somthing when I have an constructor.
The var Class = function () {}; and the Class.prototype in the closure function with .apply(this, arguments) does the thing, that is why I can return Class in the constructor function, if I would just do
var Class = function () {
var ClassICreate = function () {};
...
return ClassICreat;
}
it would not work, because you cannot return from a constructor, because it is an object.
That is how it works for my:
var Class = (function () {
var Class = function () {
return (function (information) {
var Class = function () {};
var properties = {};
for(var key in information.properties) {
properties[key] = {
get: information.properties[key].getter,
set: information.properties[key].setter,
enumerable: !information.properties[key].hidden || true
};
};
Object.defineProperties(Class.prototype, properties);
return Class;
}).apply(this, arguments);
};
return Class;
})();
After I found the answer it looked so easy to me, and thanks for the comments, they helped my to find the right answer...
I'm running into an issue with using RequireJS and Prototypal inheritance. Here's my module:
define(function () {
function Module(data) {
this.data = data;
}
Module.prototype.getData = function () {
return this.data;
};
Module.prototype.doSomething = function () {
console.log(this.data);
console.log(this.getData());
};
return Module;
Module.prototype.callFunction = function (fn) {
if (this[fn]) {
console.log('call');
Module.prototype[fn]();
}
};
});
Then I instantiate the module, like so:
var module = new Module({ name: 'Marty' });
module.getData(); // returns { name: 'Marty' }
module.data; // returns { name: 'Marty' }
module.callFunction('doSomething') // returns undefined on the first (and second) console log
The console.logs in the module.doSomething() always return undefined. Am I misunderstanding how prototypal inheritance works with RequireJS?
As it turns out, I had written the callFunction method incorrectly. The correct way is:
Module.prototype.callFunction = function (fn) {
if (this[fn] && typeof this[fn] === "function") {
this[fn]();
}
};
The problem was using Module.prototype instead of this. Whoops.