I'm using array value as variable and then call the function N method, how I get them in function N.
I really want to simulate the Javascript array method, I don't want to use parameters to achieve it. For example,
var p1 = [1,2,3,4,5]; p1.push(6);
function _Array() {
this._this = this;
}
_Array.prototype.show = function () {
this._this.forEach(function(item){alert(item);}) //how to print 1,2,3,4,5
};
var p1 = [1,2,3,4,5];
p1 = new _Array();
//p1._Array.call(p1); //not work
// new _Array().show.call(p1); //not work
// p1.show(); //not work
You have to store that in the instance
function N(arr) {
this._this = arr
}
N.prototype.say = function () {
this._this.forEach(function (item) {
console.log(item)
})
}
p1 = new N([1, 2, 3, 4, 5])
p1.say()
If you are insistent on wanting to write a method that takes the array by reference, you can modify the array prototype like so:
Array.prototype.show = function() {
this.forEach(item => alert(item));
}
However, it is a VERY BAD IDEA to modify the built in object prototypes, as this can cause conflicts with external libraries implementing their own "show" function that is being used differently, or cause incompatibilities with future versions of JS that implements this method.
It would be far more prudent in most situations to pass the array as a parameter, unless you have a very specific reason why you're not doing so. In that case, you should at least prefix the method with some sort of project identifier to minimize the chances of conflicts occurring.
Related
I have this code that is called in an ajax callback once the data is fetched:
function onFetchCallback(data) {
onFetchCallback.accumData ??= [];
onFetchCallback.timeLine ??= [];
onFetchCallback.tempValues1 ??= [];
onFetchCallback.tempValues2 ??= [];
onFetchCallback.char;
const hasNulls = data.includes(null);
if (!hasNulls) {
//push values into different arrays
} else {
//push the rest of no nulls if there is any...
}
}
I dont find this clean, bacause I am checking if the arrays that accumulate the data are initialized for every callback call. I think it woull be better to have the callback function initialized, so that the arrays are created, and then call the functions that will store the data in the arrays.
So I did:
function onFetchCallback() {
function init() {
onFetchCallback.accumData ??= [];
onFetchCallback.timeLine ??= [];
onFetchCallback.tempValues1 ??= [];
onFetchCallback.tempValues2 ??= [];
onFetchCallback.char;
}
function store(data) {
const hasNulls = data.includes(null);
if (!hasNulls) {
//push values into different arrays
} else {
//push the rest of no nulls if there is any...
}
}
onFetchCallback.init = init;
onFetchCallback.store = store;
}
So then when I need to use my callback I do:
onFetchCallback();
onFetchCallback.init();
myWhateverFunc(onFetchCallback.store);
Being myWhateverFunc the one calling the callback:
function myWhateverFunc(callback) {
$.ajax({
//whatever
})
.done(function (data) {
callback(data); //CALL
});
}
This works and I find it super javasScriptic so I do it all the time. Meaning the onFetchCallback initialization + other methods call to handle the function members. I do not know js in depth so I would like to know of there are any flaws with this pattern, or if there is any other better/cooler/javaScriptStylish way to do this.
The pattern you're using has a lot of resemblence with the function constructor which is more commonly used in JavaScript.
An implementation of your code in the function constructor pattern would like like this:
function FetchCallback() {
this.accumData = [];
this.timeLine = [];
this.tempValues1 = [];
this.tempValues2 = [];
this.char;
}
FetchCallback.prototype.store = function(data) {
const hasNulls = data.includes(null);
if (!hasNulls) {
// push values into different arrays
} else {
// push the rest of no nulls if there is any...
}
};
It enables you to create an object with properties and methods which are predefined. This removes the hassle of repetition when you need multiple instances of this same object.
To use the constructor you'll need to create a new instance with the new keyword. This will return an object with all the properties and methods set.
const fetchCallback = new FetchCallback();
// Note the .bind() method!
myWhateverFunc(fetchCallback.store.bind(fetchCallback));
Edit
You'll need to specifically set the value of this to the created instance that is stored in fetchCallback. You can do this with the bind() method. This methods explicitly tells that this should refer to a specific object.
The reason to do this is that whenever you pass the store method as the callback to the myWhateverFunc, it loses it's context with the FetchCallback function. You can read more about this in this post
The main difference between this and your code is that here the FetchCallback function will be unaltered, where your function is reassigned every time you call onFetchCallback() and onFetchCallback.init(). The constructor pattern will result in more predictable behavior, albeit that the this keyword has a learning curve.
If I have an array of objects like:
function Fruit() {
this.onTree = true;
}
Fruit.prototype.pick = function() {
this.onTree = false;
};
var arr = [new Fruit(), new Fruit()];
Is there any way to use Array.forEach to call the pick method on each one without creating an extra anonymous function?
arr.forEach(function(f) { f.pick(); });
I thought maybe I could do something with Fruit.prototype.pick.call but then the this context of the call function is lost so I have to bind that and I end up with:
arr.forEach(Function.call.bind(Fruit.prototype.pick));
which works but it's pretty ugly. Basically I just want something like this from Java:
arr.forEach(Fruit::pick);
You can use many approaches, but at least you need to pass a function to forEach because that is it's syntax. But if you use ES6, you can work with arrow functions and it can be more beautiful.
arr.forEach(f => f.pick());
You missed () after Fruit definition, didn't you?
function Fruit() {
this.onTree = true;
}
Fruit.prototype.pick = function() {
this.onTree = false;
};
var arr = [new Fruit(), new Fruit()];
arr.forEach(function(val, index) {
val.pick();
console.log(val);
})
I tested that one nd it change those fruit.onTree into false.
If you cannot use ES6 (but, well, it's 2017...) you can store your this reference
var self = this;
function invoker(item){
Item.pick.call(self);
}
array.forEach(invoker)
Or just use a for loop
What is the meaning of return { push:function ..... in below code snippet. When I googled I found that push() method adds new items to the end of an array, and returns the new length. So I am not sure what is push:. It seems to be some kind of syntax. Can someone please explain me.
function(notificationsArchive) {
var MAX_LEN = 10;
var notifications = [];
return {
push: function(notification) {
var notificationToArchive;
var newLen = notifications.unshift(notification);
//push method can rely on the closure scope now!
if (newLen > MAX_LEN) {
notificationToArchive = this.notifications.pop();
notificationsArchive.archive(notificationToArchive);
}
},
// other methods of the NotificationsService
};
The method push you are referencing has nothing to do with push with Arrays, it is a public method exposed by the module pattern. It only exposes methods and properties that the author of the code wants you to be able to call/set. It hides the variables MAX_LEN and notifications so they can not be changed from outside.
References on OO Module patterns:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript
http://www.raymondcamden.com/2013/05/13/JavaScript-Design-Patterns-The-Revealing-Module-Pattern
Somewhere a constructor is defined like
var Something = function() {
// do stuff
}
If I could insert the line
mydebug.Something = this;
at the beginning, I could store the most recently created instance of Something, which would help me debugging. I can't, but I get passed the Something (the function and its name) and can replace it by something else. I just don't know how to make the "something else" to behave like the original.
function intercept(someConstructor, someName) {
return function <<someName>> () { // 1
var result = <<create a new instance>>; // 2
mydebug[someName] = result;
return result;
}
}
which would get called as
intercept(Something, "Something")
There are at least two problems:
I don't know how to create a function having a name given by a variable.
I don't know how to create the instance.
For 1:
Depending on where you are storing that function you don't have to name it in your intercept implementation.
You can just do return function () { ... or you can do something similar to someObject[someName] = function()... and then return someObject[someName].
For 2:
If I understand correctly you should be able to just do var result = new someConstructor();, but I'm not 100% clear on your goal.
i have a problem using a class methods, after it was inserted into array. when i pull it back i can no longer use it methods.
and i know javascript does not have class, when i say class i mean object -or js equal.
suppose i have the following:
// a simple atomic class
function raw_msg(msg) {
this.msg = msg;
this.print = function () {
console.log(this.msg);
}
}
// and then i have this container for this "atomic" class
// which accept array of unknown object (known to me though..) = in_buffer
// i.e in_buffer is just an array of objects (one type of object)
function buffer(in_buffer) {
this.trans_buffer = null;
if (in_buffer!=null)
this.set_buffer (in_buffer);
this.set_buffer = function (buffer) {
this.trans_buffer = [];
var length = buffer.length,
row, new_raw_msg;
for(var x = 0; x < length; x++) {
row = buffer[x];
this.trans_buffer.push(new raw_msg(row));
}
console.log(this.trans_buffer);
}
this.use_some_raw_msg_method = function () {
var firstrow = this.trans_buffer[0];
firstrow.print(); // here is the problem!!!
//this here where i need help as it yield the error:
//Uncaught TypeError: Object #<Object> has no method 'print'
}
}
// this is how i use it, this code sits in a diffrent yet another class...
// this here im just building fake array
var buffer_in = [];
for (var x=0;x<10;x++)
buffer_in.push ("whatever" + x);
this.trans_buffer = new trans_helper(buffer_in);
this.trans_buffer.use_some_raw_msg_method (); // will yield the error as described
i hope this here, is clear, ask away if you need clarifications.
thanks for your help!
note to future readers - there is no problem in retrieving an object and using its methods.
You had several problems with your code.
Associative array does not have .push() method so the following line failed:
buffer_in.push ("whatever" + x);
To fix this just declare plain array:
var buffer_in = [];
You tried to create instance of function called trans_helper which does not exist. The name is buffer instead, so fix would be:
var trans_buffer = new buffer(buffer_in);
Last but not least, you tried to call function in the "class" when it still did not exist yet. JavaScript does not "compile" functions in advance, when inside function it will go line by line. So in this line in your code:
this.set_buffer (in_buffer);
There was still no function called "set_buffer" in your class. To fix this, place the function declaration above, on top.
Live test case.