Javascript Callable and prototype extendable Function - javascript

Basically I looking for the ability to attach methods to an executable function while using the javascript prototype method. The code below demonstrates want I'm talking about and the functionality I'm looking for, but it is really a hack. Notice I have a valid this object to attach variables along with a main and init function.
function create(){
var $this = {},
main = function(){
prototype.main.apply($this,arguments);
};
prototype.init.apply($this,arguments);
//Add additional prototype methods by brute force, ugly
for(i in prototype)-function(i){
main[i]=function(){
prototype[i].apply($this,arguments);
}
}(i);
return main;
};
var prototype = {
//called when you create the object
init:function(text){
console.log('init');
this.text = text;
},
//called when you call the object
main:function(){
console.log('main');
console.log(this);
},
method:function(){
console.log(this.text);
}
};
//create returns a function that also has methods
//the below line will call the init method
var fun = create('some variables');
//call main function
fun();
//call methods
fun.method();
I'm afraid I might be missing something obvious.
Here is the same functionality as above, but instead extends the global function prototype.
Extending the global properties is bad practice, so I am looking for a alternative solution.
Function.prototype = {
//called when you create the object
init:function(text){
console.log('init');
this.text = text;
},
//called when you call the object
main:function(){
console.log('main');
console.log(this);
},
method:function(){
console.log(this.text);
}
};
function create(){
var ret = function(){
ret.main.call(main);
};
ret.init.apply(main,arguments);
return ret;
};
//create returns a function that also has methods
//the below line will call the init method
var fun = create('some variables');
//call main function
//fun();
//call methods
fun.method();
Just as an obvious point, it doesn't appear you can use the typical new object approach because if you call new you can't return a separate value.
Any explanation or considerations would be great!

You can put your the prototype functions into the "constructor" body. This technically is what you are currently doing, but defining them explicitly rather than using a helper method is much cleaner. Then, you can further simplify your code using the following pattern for public and private variables and methods:
function Fun(text) {
// This is the main function
var fn = function () {
return 'main';
};
// Attach public variables and methods
fn.publicVariable = 'public';
fn.publicMethod = function () {
return text; // text is a "private variable"
};
// Do whatever initialization
console.log('init');
// Return the main function
return fn;
}
var fun = Fun('this is some text'); // "init"
fun() // "main"
fun.publicMethod() // "this is some text"
console.log(fun.publicVariable); // "public"
console.log(fun.text); // undefined

By "the JavaScript prototype method", do you mean using the Function.prototype property to implement inheritance? Or are you just trying to create functions that have an initializer and attached methods?
Your example does the latter, so I'll assume that's what you you're looking for. Does this do what you're looking for?
function create(text)
{
var main = function()
{
console.log('main');
console.log(this);
}
var init = function()
{
console.log('init');
main.text = text;
}
main.method = function()
{
console.log(main.text);
}
init();
return main;
}
//the following line will call init
var fun = create('some variables');
//call main
fun();
//call methods
fun.method();

Related

Calling one method of an object in another

I have a prototype:
var myClass = function() {};
I have a method on that class:
myClass.prototype.method1() = function() {
return x;
}
I then have a second method which I declare in the same way, but I want to access the result of method1() in it. But this doesn't work, and I'm not sure why...
myClass.prototype.method2() = function() {
return myClass.method1();
}
I get TypeError: myClass.method1 is not a function
Can anyone point out what's syntactically/conceptually wrong with this? And suggest any improvements?
Also I'm not 100% I'm using the terms 'class' and 'prototype' correctly in this instance. If anyone can correct the terminology, or point out any other terminology associated with this kind of process I'd appreciate it!
Thanks in advance.
var myClass = function() {};
This is a constructor and not a prototype. Here's a quick read explaining the difference.
You can call it using this. Here's the best place for a brush up.
const MyClass = function() {};
MyClass.prototype.method1 = function() {
return x;
}
MyClass.prototype.method2 = function() {
return this.method1();
}
Also, no need for brackets in function definitions of method1 and method2
That's because (using rough OO terminology), method1() is an instance method, and you're trying to call it as a static method.
const MyClass = function() {}; // MyClass is a constructor
MyClass.prototype.method1() = function() {
return x;
}
MyClass.prototype.method2() = function() {
return this.method1(); // Call it as an instance
}
or, alternatively:
const MyClass = function() {};
MyClass.method1() = function() { // "static" method
return x;
}
MyClass.prototype.method2() = function() {
return MyClass.method1(); // Call it as a "static"
}
Worth noting that this terminology is misleading, there are no static or instance methods (in fact, there are no methods in JavaScript, only functions, and properties that hold references to functions).
The JS oop has some difference between public and privileged methods.
myClass.method1(); is A static method calling. it's just like a normal function and has no relation with any myClass object instance.
So you need to call it using the Full namespace:
MyClass.method1()

how can i call a javascript function in another function?

this is my class
function User(){
this.nickname='nickname';
}
User.prototype.save=function(){
dosomething();
};
User.prototype.add=function(){
dosometing();
call save();
};
i want to call the save() function in the add() function,but i don't know how to do.I tried
User.prototype.add=function(){
save();
};
and
User.prototype.add=function(){
User.prototype.save();
};
but both are wrong,and what should i do?
function User() {
this.nickname = 'nickname';
}
// ...
User.prototype.add = function() {
this.save();
};
You were not defining your User constructor properly.
Also, instances of User (created like var myUser = new User(); ) can access their prototype's methods via this.methodNameHere();
Ok.There are a few mistakes in your code.
Here we are using the classical model of inheritance.
Step 1.Create a constructor function. eg. function user(){...}
Step 2.Extend your prototype by adding methods.eg add,save etc
step 3.Create an instance to call methods.eg.MyInstance
function User(){
this.nickname='nickname';
}
User.prototype.dosomething=function(){
//some code
};
User.prototype.save=function(){
this.dosomething();
};
User.prototype.add=function(){
this.dosometing();
this.save();
};
Now lets say I want to call a method add.This is how its done.
var MyInstance = new User();//create an instance.
MyInstance.add();//call the function.
Outside the scope of your question : The same thing could be done by Prototypal Inheritance as well.
var UserPrototype={
save:function(){..},
add:function(){
this.save();
}
}
var MyInstance = Object.Create(UserPrototype);
MyInstance.add();

Difference between javascript constructors

I'm having a bit of confusion over which (if any) of these javascript initializes to use, as from what I can tel, they all do the same thing. Are there cases in which I should use one or he other? Mt project requires me to encapsulate several functions and namespaces in a single object so that we don't clutter te global scope with variable names, put I'm especially unclear as to the difference between +function(){}(); and (function())();
Any help would be greatly appreciated. Keep in mind the end goal is for all of our function to be encapsulated in a single namespace. IE MyCompany.function, MyCompany.Namepsace.Function ...
<script>
var Ford = {};
+function() {
Ford.start = function() {
console.log("Ford just started");
};
}();
Ford.start();
</script>
<script>
var Honda = {};
(function() {
Honda.start = function() {
console.log("Honda just srtarted");
};
})();
Honda.start();
</script>
<script>
var Toyota = function() {
return {
start: function() {
console.log("Toyota just strted");
}
};
}
var car = new Toyota();
car.start();
</script>
Javascript functions are only invoked as constructors when the new keyword is used. new creates a new object instance, inherits from the constructor's prototype, and makes the context of the this keyword the newly created object instance. So if you're not using the prototype to inherit properties or the keyword this to create new properties in the constructor--you don't really need to use a constructor.
I think what you're looking for is the module pattern which is implemented using immediately invoked functions. Both of your first two examples use immediately invoked functions. I believe the style (function(){}()); is preferred to +function(){}();. Both the surrounding () and the + cause the javascript parser to expect a function expression rather than a function declaration and this allows the trailing () to invoke the function. Besides being somewhat less readable + may also alter the return value of the function.
I think you want some variation on this (copied from link):
var MODULE = (function () {
var module = {};
var privateVariable = 1;
function privateMethod() {
// ...
}
module.moduleProperty = 1;
module.moduleMethod = function () {
// ...
};
return module;
}());
While all of that is valid JS, you're making assumptions that lead me to believe you may not understand how JS works. The first two example are not constructors in the usual sense at all...they're sort of module pattern, but not even. you could condense it to
var Honda = {};
Honda.start = function() { console.log("Honda just started"); }
and forget the self-executing function. What is shown above is similar to what you'd think of as a static function in other languages:
public class Honda {
public static void start() { Console.WriteLine("Honda Just Started"); }
}
If you wanted an instance function, you need to either attach to the prototype, or to the this keyword in the constructor:
Prototype:
var Honda = function() {}
Honda.prototype.start = function() { console.log("Honda just started"); }
This:
var Honda = function() {
this.start = function(){
console.log("Honda just started");
}
}
Your final example, with Toyota indicates you have a fundamental misunderstanding of how function constructors work. Your object has been discarded, and in return you get some object literal which could have been written:
var Toyota = {
start: function(){
console.log("Toyota just started");
}
}
What you (probably) intend is the "this" pattern I explained on the Honda example above:
var Toyota = function() {
this.start = function() {
console.log("Toyota just started");
}
}
Finally, when writing "namespaced" libraries of functions, the module pattern may be your best friend. This lets you maintain private state without the need for a formal constructor/prototypes, etc:
var MyCompany = {};
//car module
(function(ns){
var module,
_isStarted;
function start() { console.log('start'); _isStarted = true; }
function stop() { console.log('stop'); _isStarted = false; }
function isStarted() { return _isStarted; }
module = {
start: start,
stop: stop,
isStarted: isStarted
}
ns.CarModule = module;
}(MyCompany));
//use:
MyCompany.CarModule.start();
if(MyCompany.CarModule.isStarted()) { MyCompany.CarModule.stop(); }

javascript class inherit from Function class

I like that in javascript, I can create a function, and then add further methods and attributes to that function
myInstance = function() {return 5}
myInstance.attr = 10
I would like to create a class to generate these objects. I assume I have to inherit from the Function base class.
In other words, I would like to:
var myInstance = new myFunctionClass()
var x = myInstance()
// x == 5
But I don't know how to create the myFunctionClass. I have tried the following, but it does not work:
var myFunctionClass = function() {Function.call(this, "return 5")}
myFunctionClass.prototype = new Function()
myInstance = new myFunctionClass()
myInstance()
// I would hope this would return 5, but instead I get
// TypeError: Property 'myInstance' of object #<Object> is not a function
I also tried the more complicated (and more proper?) inheritance method found here: How to "properly" create a custom object in JavaScript?, with no more luck. I have also tried using the util.inherits(myFunctionClass, Function) found in node.js. Still no luck
I have exhausted Google, and therefore feel that I must be missing something fundamental or obvious. Help would be greatly appreciated.
Your trying to inherit from Function. This is a right pain to do. I suggest you do the following instead
Live Example
var Proto = Object.create(Function.prototype);
Object.extend(Proto, {
constructor: function (d) {
console.log("construct, argument : ", d);
this.d = d;
// this is your constructor logic
},
call: function () {
console.log("call", this.d);
// this get's called when you invoke the "function" that is the instance
return "from call";
},
method: function () {
console.log("method");
// some method
return "return from method";
},
// some attr
attr: 42
});
You want to create a prototype object that forms the basis of your "class". It has your generic methods/attributes. It also has a constructor that gets invoked on object construction and a call method that gets invoked when you call the function
var functionFactory = function (proto) {
return function () {
var f = function () {
return f.call.apply(f, arguments);
};
Object.keys(proto).forEach(function (key) {
f[key] = proto[key];
});
f.constructor.apply(f, arguments);
return f;
}
}
A function factory takes a prototype object and returns a factory for it. The returned function when called will give you a new function object that "inherits" from your prototype object.
var protoFactory = functionFactory(proto);
var instance = protoFactory();
Here you create your factory and then create your instance.
However this isn't proper prototypical OO. we are just shallow copying properties of a prototype into a new object. So changes to the prototype will not reflect back to the original object.
If you want real prototypical OO then you need to use a hack.
var f = function () {
// your logic here
};
f.__proto__ = Proto;
Notice how we use the non-standard deprecated .__proto__ and we are mutating the value of [[Prototype]] at run-time which is considered evil.
JS does not allow a constructor to return a function, even though functions are objects. So you cant have an instantiation of a prototype that is itself executable. (Am I right in this? please correct if I'm not, it's an interesting question).
Though you could do a factory function:
var makeCoolFunc = function() {
var f = function() { return 5 };
f.a = 123;
f.b = 'hell yes!'
return f;
};
var func = makeCoolFunc();
var x = func();
You can extend Function and pass the wanted function body as String to the super constructor. The context of the function can be accessed with arguments.callee.
Example for an observable Attribute class:
export default class Attribute extends Function {
constructor(defaultValue){
super("value", "return arguments.callee.apply(arguments);");
this.value = defaultValue;
this.defaultValue = defaultValue;
this.changeListeners = [];
}
apply([value]){
if(value!==undefined){
if(value!==this.value){
var oldValue = this.value;
this.value=value;
this.changeListeners.every((changeListener)=>changeListener(oldValue, value));
}
}
return this.value;
}
clear(){
this.value=undefined;
}
reset(){
this.value=this.defaultValue;
}
addChangeListener(listener){
this.changeListeners.push(listener);
}
removeChangeListener(listener){
this.changeListeners.remove(listener);
}
clearChangeListeners(){
this.changeListeners = [];
}
}
Example usage:
import Attribute from './attribute.js';
var name= new Attribute();
name('foo'); //set value of name to 'foo'
name.addChangeListener((oldValue, newValue)=>{
alert('value changed from ' +oldValue+ ' to ' +newValue);
});
alert(name()); //show value of name: 'foo'
name('baa'); //set value of name to new value 'baa' and trigger change listener

What is the use of the init() usage in JavaScript?

What is the meaning and usage of the init() function in JavaScript?
JavaScript doesn't have a built-in init() function, that is, it's not a part of the language. But it's not uncommon (in a lot of languages) for individual programmers to create their own init() function for initialisation stuff.
A particular init() function may be used to initialise the whole webpage, in which case it would probably be called from document.ready or onload processing, or it may be to initialise a particular type of object, or...well, you name it.
What any given init() does specifically is really up to whatever the person who wrote it needed it to do. Some types of code don't need any initialisation.
function init() {
// initialisation stuff here
}
// elsewhere in code
init();
In JavaScript when you create any object through a constructor call like below
step 1 : create a function say Person..
function Person(name){
this.name=name;
}
person.prototype.print=function(){
console.log(this.name);
}
step 2 : create an instance for this function..
var obj=new Person('venkat')
//above line will instantiate this function(Person) and return a brand new object called Person {name:'venkat'}
if you don't want to instantiate this function and call at same time.we can also do like below..
var Person = {
init: function(name){
this.name=name;
},
print: function(){
console.log(this.name);
}
};
var obj=Object.create(Person);
obj.init('venkat');
obj.print();
in the above method init will help in instantiating the object properties. basically init is like a constructor call on your class.
NB. Constructor function names should start with a capital letter to distinguish them from ordinary functions, e.g. MyClass instead of myClass.
Either you can call init from your constructor function:
var myObj = new MyClass(2, true);
function MyClass(v1, v2)
{
// ...
// pub methods
this.init = function() {
// do some stuff
};
// ...
this.init(); // <------------ added this
}
Or more simply you could just copy the body of the init function to the end of the constructor function. No need to actually have an init function at all if it's only called once.
This is more like unreachable code
eg. if variable x or function x() is declared below the line where its
called this error generates:
setPlayerOne();
let imageGenerator = (value) =>{
allImages = {
1: 'images/dice1.png',
2: 'images/dice2.png',
3: 'images/dice3.png',
4: 'images/dice4.png',
5: 'images/dice5.png',
6: 'images/dice6.png',
}
return allImages[Number(value)];
}
findRandom = () =>{
let randomNumber = Math.floor(Math.random() * 6) +1
return randomNumber;
}
let setPlayerOne = () =>{
let img1 = document.querySelector('.img1').attributes.src;
img1.value = imageGenerator(findRandom())
}
let setPlayerTwo = () =>{
let img2 = document.querySelector('.img2').attributes.src;
img2.value = imageGenerator(findRandom())
}
setPlayerTwo();
setPlayerOne() method will generate this but setPlayerTwo() will not generate;
this because setPlayerOne() was called before initialized by JS.

Categories

Resources