I'm going to add one extra update function on push method, code is below:
function update() {
console.log("update");
}
let method = 'push';
let oldMethod = Array.prototype[method];
Array.prototype[method] = function () {
update();
oldMethod.call(this,...arguments);
}
Can someone explain why I should use oldMethod.call(this,...arguments) rather than oldMethod() only?
If you don't invoke the "real" .push() with .call(), the value of this (the array into which new values are to be pushed) will be unbound and it won't work.
Related
I am building a battleship game in js. I added event listener on targeted element of the grid and I am trying to make a function that takes one argument (boat length) and according to that argument, function should render the boat on my grid. Problem is that no matter what argument I passed in to the function it renders the boat same length. I think that problem is event listener that stays the same when I clicked the element first time.
Here is the code:
function placeBoat (boatLength){
domElements.yourGrid.onclick = function(event){
let target = event.target;
console.log(event)
let clickedPosition = target.id
let clickedPositionId = clickedPosition.slice(4, 6)
let clikedPositionInt = parseInt(clickedPositionId);
for(let i = 0; i < boatLength; i++){
target.style.background = "green";
target = document.querySelector("#cell" + clikedPositionInt)
clikedPositionInt += 10;
}
}
}
domElements.boat1Button.addEventListener("click", placeBoat(3))
domElements.boat2Button.addEventListener("click", placeBoat(4))
domElements.boat3Button.addEventListener("click", placeBoat(5))
addEventListener's second argument is the listener function ( https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener ). However, you're calling the function placeBoat instead of passing a function as an argument.
Let's start with a simple explanation. Define some new functions without arguments and add event listeners using them:
function placeBoat3() {
placeBoat(3);
}
function placeBoat4() {
placeBoat(4);
}
function placeBoat5() {
placeBoat(5);
}
domElements.boat1Button.addEventListener("click", placeBoat3)
domElements.boat2Button.addEventListener("click", placeBoat4)
domElements.boat3Button.addEventListener("click", placeBoat5)
As you can see, now second arguments to addEventListener are function names without parenthesis. Once you are comfortable with that idea, you can move forward and use arrow functions. Get rid of the new functions and call addEventListeners like below:
domElements.boat1Button.addEventListener("click", () => placeBoat(3))
domElements.boat2Button.addEventListener("click", () => placeBoat(4))
domElements.boat3Button.addEventListener("click", () => placeBoat(5))
() => placeBoat(3) is a shorthand to define a function with no arguments and which calls placeBoat(3) in its body. You can learn more about them at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
I am trying to implement a switch statement alternative using a map object and the functions that are supposed to be called according to the condition are being called while I'm declaring the map
Here is a simplified code of what I implemented
someMethodName(someParams, otherParams) {
const verifyThis = callExternalApi(someParams);
const customSwitch = {
oneValue: this.doThis(otherParams),
anotherValue: this.doThat(otherParams),
};
const possibleValues = ["oneValue", "anotherValue"];
if (possibleValues.includes(verifyThis))
return customSwitch[verifyThis];
return this.defaultCase(otherParams);
}
I put a console.log in the methods to be called and found out that they are all being called, supposedly while I'm declaring customSwitch, and then one of the methods are being called when going through the if clause.
How do I work around this to avoid calling my methods?
Use an object whose values are functions which, when called, invoke the other functions:
const customSwitch = {
oneValue: () => this.doThis(otherParams),
anotherValue: () => this.doThat(otherParams),
};
and invoke when returning by doing
return customSwitch[verifyThis]();
I am currently working on a project where I want to deference an array of functions (function references) and excecute the function.
This does only work, if I don't call another class method within the function.
Otherwise I get "Uncaught TypeError" and I can't figure out how to solve this error.
Here's my code sample 'working' the same way my original project does:
After calling function2 the engine cannot find this.log...
Do you have ideas? Thank you very much in advance.
KR, Robert
class ArrayWithFunctions {
constructor() {
this.functionTable = [
this.function1,
this.function2,
];
}
execute(index) {
return (this.functionTable[index])();
}
log(chars) {
console.log(chars);
}
function1() {
console.log('I am Function 1.');
}
function2() {
this.log('I am Function 2.');
}
}
let example = new ArrayWithFunctions();
example.execute(0);
example.execute(1);
This is an example of Javascript's execution contexts in action. In this situation, to avoid losing the correct reference to the class, you can bind the functions when putting them inside the array, or initialize them as arrow functions:
Example 1: Bind them in the constructor:
constructor() {
this.functionTable = [
this.function1.bind(this),
this.function2.bind(this),
];
}
Example 2: Create them as arrow functions:
class ArrayWithFunctions {
// ...
function1 = () => {
console.log('I am Function 1.');
}
function2 = () => {
this.log('I am Function 2.');
}
}
You can use arrow functions to dodge scoping issues:
function2 = () => {
this.log('I am function 2.');
}
Related: How to access the correct `this` inside a callback (and you might also want to take a look at How does the "this" keyword work?).
In this case you can simply set the correct this value by calling the function with .call:
return this.functionTable[index].call(this);
This is my function, I'm trying to return a value.
var operations = function() {
this.selectedQueryBy = function() {
return jQuery('input[type="radio"][name="selectRadio"]:checked').attr("id")
},
this.submitForm = function() {
jQuery('.btns').hide();
var queryBy = this.selectedQueryBy;
}
}
Im trying to get the value of "selectedqueryby" which is already defined in the function. It returns the whole function instead of the radio button. Is the calling way correct?
Please let me know where Im doing wrong.
I'll call the submitForm event on clicking a button.
You need to add parentheses to call the function:
var queryBy = this.selectedQueryBy();
// ^^
Otherwise you're just referring to the function itself instead of calling it.
I'm trying to call a function without re-initializing (hope I used the correct word here) it every time I call it. So the first time it gets called, it should initialize, but after its initialized, it should just use that reference.
Here's the code I'm trying to do it with.
JSFiddle
console.clear();
function mainFunction(e) {
var index = 0;
function subFunction() {
console.log(index++);
}
return subFunction();
}
window.addEventListener('click', mainFunction)
index should increase by one every time mainFunction gets called. The obvious solution, is to make index a global variable (or just out of mainFunction). But I need index to stay inmainFunction`.
How can I make index increment every time (using the same reference) mainFunction gets called?
I tried assigning mainFunction to a variable, then calling the variable in the event listener,
var test = mainFunction;
window.addEventListener('click', test)
but that didn't work. The results were the same.
You should correct the code as follows;
console.clear();
function mainFunction(e) {
var index = 0;
function subFunction() {
console.log(index++);
}
return subFunction; // <<< don't invoke subfunction
}
window.addEventListener('click', mainFunction()) // <<< invoke mainfunction
maybe try closures?
var main = (function () {
var index = 0;
return function () {return index += 1;}
})();
main()
main()
//index should be 2...
explain-
The variable main is assigned the return value of a self-invoking function.
The self-invoking function only runs once. index initialize only once.
If you don't want to make index global (or one scope higher regarding mainFunction), you can use a closure:
var mainFunction = (function () {
var index = 0;
return function () {return console.log(index++);}
})();
<button onclick="mainFunction()">Click</button>
Using OOP concept is the proper way to achieve this. The following should help you.
If you want to do it in ES6 way follow this babel example
var mainFunction = function(val) {
this.index = val //initialize this with the fn parameter or set a atatic value
}
mainFunction.prototype.subFunction = function() {
return this.index++
}
var instance = new mainFunction(0)
window.addEventListener('click', function() {
console.log(instance.subFunction())
})
<p>Click to see the result </p>