JavaScript library set this to an element - javascript

I am working on a jQuery like javascript library. The syntax vill go as follows:
tex(selector).function();
In my javascript library, I have this:
(function(){
var tex = function(selector){
//selection code here
},
tex.prototype = {
// prototype functions here
}
})();
The problem that I have is how do I set this to equal the element. I have already tried this = document.getElement... but it didn't work. I know jQuery does this somehow but I haven't how.
Does anyone know how I can do this? Thank you so much.

You can only do it when you're calling a function, typically by using Function#call or Function#apply:
function foo() {
console.log("name = " + this.name);
}
var obj = {name: "Fred"};
foo.call(obj); // Outputs "Fred"
There, we call the foo function using call, passing in obj as the value to use as this during the call.
Applying that to a DOM element:
function foo() {
console.log("My id is " + this.id);
}
var elm = document.getElementById("whatever");
foo.call(elm); // "My id is whatever"
The value to use as this during the call is the first argument to call and apply. The only difference between the two is how you pass arguments to the function (foo, in our example above): With call, you pass them as subsequent discrete arguments:
theFunction.call(thisArg, firstArg, secondArg, thirdArg);
With apply, you give it an array of args:
var args = [firstArg, secondArg, thirdArg];
theFunction.apply(thisArg, args);
// or (of course)
theFunction.apply(thisArg, [firstArg, secondArg, thirdArg]);
// Note -------------------^-----------------------------^
So a more complete example:
function foo(firstArg, secondArg, thirdArg) {
console.log("name = " + this.name);
console.log("firstArg = " + firstArg);
console.log("secondArg = " + secondArg);
console.log("thirdArg = " + thirdArg);
}
var obj = {name: "Fred"};
// These two calls do exactly the same thing:
foo.call(obj, "one", "two", "three");
foo.apply(obj, ["one", "two", "three"]); // Note the [ and ]

jQuery does this by passing the selected elements as context to the callback function.
For instance...
tex.prototype = {
// prototype functions here
someMethod: function(callback) {
callback.apply(this, arguments);
}
}
You can pass any javascript object for the context, so this in the example above could be your selected element(s).
Edit:
For clarity. You could do this in your tex function.
var element;
var tex = function(selector){
element = document.getElementById(selector);
}
And then in the first example, use element instead of this.
As a side note, your tex variable isn't currently accessible outside of your self-executing anonymous function.

Related

About dynamic dispatch in the book-[Programming JavaScript Applications]

I meet a problem about dynamic dispatch. The following is the code snippet which from the book [Programming JavaScript Applications], and I put it on https://jsfiddle.net/abramhum/bbfxxwok/1/
function equals(a, b, c) {
console.log("a[=]" + a);
if (a == b) {
console.log(c);
}
}
function test(a, fn) {
console.log(a + " ---start function[=]");
fn.apply(this);
console.log(a + " ---Fnished");
}
var methods = {
init: function(args) {
return 'initializing...';
},
hello: function(args) {
return 'Hello, ' + args;
},
goodbye: function(args) {
return 'Goodbye, cruel ' + args;
}
},
greet = function greet(options) {
var args = [].slice.call(arguments, 0),
initialized = false,
action = 'init'; // init will run by default
if (typeof options === 'string' &&
typeof methods[options] === 'function') {
action = options;
args.shift();
}
return methods[action](args);
};
test('Dynamic dispatch', function() {
var test1 = greet(),
test2 = greet('hello', 'world!'),
test3 = greet('goodbye', 'world!');
equals(test2, 'Hello, world!',
'Dispatched to hello method.');
equals(test3, 'Goodbye, cruel world!',
'Dispatched to goodbye method.');
});
There exist two subjects in this problem, one is when greet("goodbye", "world") is executed, why it called greet(options), and the value about options is indeed the fist parameter, like "goodbye", and the "world" can be get via arguments; The second is var methods ={...}, it get the arguments like init, and return the value if matching the declare, like init:function(args){...}, but it indeed not code style of switch, and why we can use that in javascript.
This is much unlike C codes, I don't know why, is any one know the reason?
thanks.
one is when greet("goodbye", "world") is executed, why it called greet(options), and the value about options is indeed the fist parameter, like "goodbye", and the "world" can be get via arguments
Because in a JavaScript non-arrow function, arguments is a predefined identifier referring to a pseudo-array of all of the arguments passed to the function. It has nothing to do with dynamic dispatch. It's just a feature of JavaScript functions that was useful back before JavaScript got proper variable parameter lists:
function foo() {
console.log("foo called, total arguments: " + arguments.length);
for (var n = 0; n < arguments.length; ++n) {
console.log("Arg #" + n + ":", arguments[n]);
}
}
foo();
foo("bar");
foo("biz", 42);
the second problem is var methods ={...}, it get the arguments like init
Those aren't arguments, those are properties being defined for the object assigned to methods. Just like a, b, and c here:
var obj = {
a: 42,
b: "Whatever",
c: "just cuz"
};
...and return the value if matching the declare, like init:function(args){...}, but it indeed not code style of switch, and why we can use that in javascript.
Because functions are objects, and so like any other object, you can refer to them from variables, arguments, and object properties. methods's properties init, hello, and goodbye refer to functions. You can call them via the properties: method.init().
So say we have the variable name containing "init". We can look up the property with that name on methods: methods[name]. And since that gives us a reference to a function, we can call that function.
var methods = {
init: function() {
console.log("init called");
}
};
var name = "init";
methods[name](); // "init called"
More: Dynamically access object property using variable
This is much unlike C codes, I don't know why, is any one know the reason?
Because C and JavaScript are fundamentally different languages, created with different design constraints, at different times, by different people, with different priorities and limits.

Execute function with vs without using the .call() method [duplicate]

I already know that apply and call are similar functions which set this (context of a function).
The difference is with the way we send the arguments (manual vs array)
Question:
But when should I use the bind() method ?
var obj = {
x: 81,
getX: function() {
return this.x;
}
};
alert(obj.getX.bind(obj)());
alert(obj.getX.call(obj));
alert(obj.getX.apply(obj));
jsbin
Use .bind() when you want that function to later be called with a certain context, useful in events. Use .call() or .apply() when you want to invoke the function immediately, and modify the context.
Call/apply call the function immediately, whereas bind returns a function that, when later executed, will have the correct context set for calling the original function. This way you can maintain context in async callbacks and events.
I do this a lot:
function MyObject(element) {
this.elm = element;
element.addEventListener('click', this.onClick.bind(this), false);
};
MyObject.prototype.onClick = function(e) {
var t=this; //do something with [t]...
//without bind the context of this function wouldn't be a MyObject
//instance as you would normally expect.
};
I use it extensively in Node.js for async callbacks that I want to pass a member method for, but still want the context to be the instance that started the async action.
A simple, naive implementation of bind would be like:
Function.prototype.bind = function(ctx) {
var fn = this;
return function() {
fn.apply(ctx, arguments);
};
};
There is more to it (like passing other args), but you can read more about it and see the real implementation on the MDN.
They all attach this into function (or object) and the difference is in the function invocation (see below).
call attaches this into function and executes the function immediately:
var person = {
name: "James Smith",
hello: function(thing) {
console.log(this.name + " says hello " + thing);
}
}
person.hello("world"); // output: "James Smith says hello world"
person.hello.call({ name: "Jim Smith" }, "world"); // output: "Jim Smith says hello world"
bind attaches this into function and it needs to be invoked separately like this:
var person = {
name: "James Smith",
hello: function(thing) {
console.log(this.name + " says hello " + thing);
}
}
person.hello("world"); // output: "James Smith says hello world"
var helloFunc = person.hello.bind({ name: "Jim Smith" });
helloFunc("world"); // output: Jim Smith says hello world"
or like this:
...
var helloFunc = person.hello.bind({ name: "Jim Smith" }, "world");
helloFunc(); // output: Jim Smith says hello world"
apply is similar to call except that it takes an array-like object instead of listing the arguments out one at a time:
function personContainer() {
var person = {
name: "James Smith",
hello: function() {
console.log(this.name + " says hello " + arguments[1]);
}
}
person.hello.apply(person, arguments);
}
personContainer("world", "mars"); // output: "James Smith says hello mars", note: arguments[0] = "world" , arguments[1] = "mars"
Answer in SIMPLEST form
Call invokes the function and allows you to pass in arguments one by
one.
Apply invokes the function and allows you to pass in arguments
as an array.
Bind returns a new function, allowing you to pass in a
this array and any number of arguments.
Apply vs. Call vs. Bind Examples
Call
var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};
function say(greeting) {
console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}
say.call(person1, 'Hello'); // Hello Jon Kuperman
say.call(person2, 'Hello'); // Hello Kelly King
Apply
var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};
function say(greeting) {
console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}
say.apply(person1, ['Hello']); // Hello Jon Kuperman
say.apply(person2, ['Hello']); // Hello Kelly King
Bind
var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};
function say() {
console.log('Hello ' + this.firstName + ' ' + this.lastName);
}
var sayHelloJon = say.bind(person1);
var sayHelloKelly = say.bind(person2);
sayHelloJon(); // Hello Jon Kuperman
sayHelloKelly(); // Hello Kelly King
When To Use Each
Call and apply are pretty interchangeable. Just decide whether it’s easier to send in an array or a comma separated list of arguments.
I always remember which one is which by remembering that Call is for comma (separated list) and Apply is for Array.
Bind is a bit different. It returns a new function. Call and Apply execute the current function immediately.
Bind is great for a lot of things. We can use it to curry functions like in the above example. We can take a simple hello function and turn it into a helloJon or helloKelly. We can also use it for events like onClick where we don’t know when they’ll be fired but we know what context we want them to have.
Reference: codeplanet.io
I created this comparison between function objects, function calls, call/apply and bind a while ago:
.bind allows you to set the this value now while allowing you to execute the function in the future, because it returns a new function object.
TL;DR:
In simple words, bind creates the function, call and apply executes the function whereas apply expects the parameters in array
Full Explanation
Assume we have multiplication function
function multiplication(a,b){
console.log(a*b);
}
Lets create some standard functions using bind
var multiby2 = multiplication.bind(this,2);
Now multiby2(b) is equal to multiplication(2,b);
multiby2(3); //6
multiby2(4); //8
What if I pass both the parameters in bind
var getSixAlways = multiplication.bind(this,3,2);
Now getSixAlways() is equal to multiplication(3,2);
getSixAlways();//6
even passing parameter returns 6;
getSixAlways(12); //6
var magicMultiplication = multiplication.bind(this);
This create a new multiplication function and assigns it to magicMultiplication.
Oh no, we are hiding the multiplication functionality into magicMultiplication.
calling
magicMultiplication returns a blank function b()
on execution it works fine
magicMultiplication(6,5); //30
How about call and apply?
magicMultiplication.call(this,3,2); //6
magicMultiplication.apply(this,[5,2]); //10
It allows to set the value for this independent of how the function is called. This is very useful when working with callbacks:
function sayHello(){
alert(this.message);
}
var obj = {
message : "hello"
};
setTimeout(sayHello.bind(obj), 1000);
To achieve the same result with call would look like this:
function sayHello(){
alert(this.message);
}
var obj = {
message : "hello"
};
setTimeout(function(){sayHello.call(obj)}, 1000);
The main concept behind all this methods is Function burrowing.
Function borrowing allows us to use the methods of one object on a different object without having to make a copy of that method and maintain it in two separate places. It is accomplished through the use of . call() , . apply() , or . bind() , all of which exist to explicitly set this on the method we are borrowing
Call invokes the function immediately and allows you to pass in arguments one by
one
Apply invokes the function immediately and allows you to pass in arguments
as an array.
Bind returns a new function, and you can invoke/call it anytime you want by invoking a function.
Below is an example of all this methods
let name = {
firstname : "Arham",
lastname : "Chowdhury",
}
printFullName = function(hometown,company){
console.log(this.firstname + " " + this.lastname +", " + hometown + ", " + company)
}
CALL
the first argument e.g name inside call method is always a reference
to (this) variable and latter will be function variable
printFullName.call(name,"Mumbai","Taufa"); //Arham Chowdhury, Mumbai, Taufa
APPLY
apply method is same as the call method
the only diff is that, the function arguments are passed in Array list
printFullName.apply(name, ["Mumbai","Taufa"]); //Arham Chowdhury, Mumbai, Taufa
BIND
bind method is same as call except that ,the bind returns a function that can be used later by invoking it (does'nt call it immediately)
let printMyNAme = printFullName.bind(name,"Mumbai","Taufa");
printMyNAme(); //Arham Chowdhury, Mumbai, Taufa
printMyNAme() is the function which invokes the function
below is the link for jsfiddle
https://codepen.io/Arham11/pen/vYNqExp
Both Function.prototype.call() and Function.prototype.apply() call a function with a given this value, and return the return value of that function.
Function.prototype.bind(), on the other hand, creates a new function with a given this value, and returns that function without executing it.
So, let's take a function that looks like this :
var logProp = function(prop) {
console.log(this[prop]);
};
Now, let's take an object that looks like this :
var Obj = {
x : 5,
y : 10
};
We can bind our function to our object like this :
Obj.log = logProp.bind(Obj);
Now, we can run Obj.log anywhere in our code :
Obj.log('x'); // Output : 5
Obj.log('y'); // Output : 10
Where it really gets interesting, is when you not only bind a value for this, but also for for its argument prop :
Obj.logX = logProp.bind(Obj, 'x');
Obj.logY = logProp.bind(Obj, 'y');
We can now do this :
Obj.logX(); // Output : 5
Obj.logY(); // Output : 10
bind: It binds the function with provided value and context but it does not executes the function. To execute function you need to call the function.
call: It executes the function with provided context and parameter.
apply: It executes the function with provided context and
parameter as array.
Here is one good article to illustrate the difference among bind(), apply() and call(), summarize it as below.
bind() allows us to easily set which specific object will be bound to this when a function or method is invoked.
// This data variable is a global variable​
var data = [
{name:"Samantha", age:12},
{name:"Alexis", age:14}
]
var user = {
// local data variable​
data :[
{name:"T. Woods", age:37},
{name:"P. Mickelson", age:43}
],
showData:function (event) {
var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // random number between 0 and 1​
console.log (this.data[randomNum].name + " " + this.data[randomNum].age);
}
}
// Assign the showData method of the user object to a variable​
var showDataVar = user.showData;
showDataVar (); // Samantha 12 (from the global data array, not from the local data array)​
/*
This happens because showDataVar () is executed as a global function and use of this inside
showDataVar () is bound to the global scope, which is the window object in browsers.
*/
// Bind the showData method to the user object​
var showDataVar = user.showData.bind (user);
// Now the we get the value from the user object because the this keyword is bound to the user object​
showDataVar (); // P. Mickelson 43​
bind() allow us to borrow methods
// Here we have a cars object that does not have a method to print its data to the console​
var cars = {
data:[
{name:"Honda Accord", age:14},
{name:"Tesla Model S", age:2}
]
}
// We can borrow the showData () method from the user object we defined in the last example.​
// Here we bind the user.showData method to the cars object we just created.​
cars.showData = user.showData.bind (cars);
cars.showData (); // Honda Accord 14​
One problem with this example is that we are adding a new method showData on the cars object and
we might not want to do that just to borrow a method because the cars object might already have a property or method name showData.
We don’t want to overwrite it accidentally. As we will see in our discussion of Apply and Call below,
it is best to borrow a method using either the Apply or Call method.
bind() allow us to curry a function
Function Currying, also known as partial function application, is the use of a
function (that accept one or more arguments) that returns a new function with some of the arguments already set.
function greet (gender, age, name) {
// if a male, use Mr., else use Ms.​
var salutation = gender === "male" ? "Mr. " : "Ms. ";
if (age > 25) {
return "Hello, " + salutation + name + ".";
}else {
return "Hey, " + name + ".";
}
}
We can use bind() to curry this greet function
// So we are passing null because we are not using the "this" keyword in our greet function.
var greetAnAdultMale = greet.bind (null, "male", 45);
greetAnAdultMale ("John Hartlove"); // "Hello, Mr. John Hartlove."
var greetAYoungster = greet.bind (null, "", 16);
greetAYoungster ("Alex"); // "Hey, Alex."​
greetAYoungster ("Emma Waterloo"); // "Hey, Emma Waterloo."
apply() or call() to set this value
The apply, call, and bind methods are all used to set the this value when invoking a method, and they do it in slightly
different ways to allow use direct control and versatility in our JavaScript code.
The apply and call methods are almost identical when setting the this value except that you pass the function parameters to apply () as an array, while you have to list the parameters individually to pass them to the call () method.
Here is one example to use call or apply to set this in the callback function.
// Define an object with some properties and a method​
// We will later pass the method as a callback function to another function​
var clientData = {
id: 094545,
fullName: "Not Set",
// setUserName is a method on the clientData object​
setUserName: function (firstName, lastName) {
// this refers to the fullName property in this object​
this.fullName = firstName + " " + lastName;
}
};
function getUserInput (firstName, lastName, callback, callbackObj) {
// The use of the Apply method below will set the "this" value to callbackObj​
callback.apply (callbackObj, [firstName, lastName]);
}
// The clientData object will be used by the Apply method to set the "this" value​
getUserInput ("Barack", "Obama", clientData.setUserName, clientData);
// the fullName property on the clientData was correctly set​
console.log (clientData.fullName); // Barack Obama
Borrow functions with apply or call
Borrow Array methods
Let’s create an array-like object and borrow some array methods to operate on the our array-like object.
// An array-like object: note the non-negative integers used as keys​
var anArrayLikeObj = {0:"Martin", 1:78, 2:67, 3:["Letta", "Marieta", "Pauline"], length:4 };
// Make a quick copy and save the results in a real array:
// First parameter sets the "this" value​
var newArray = Array.prototype.slice.call (anArrayLikeObj, 0);
console.log (newArray); // ["Martin", 78, 67, Array[3]]​
// Search for "Martin" in the array-like object​
console.log (Array.prototype.indexOf.call (anArrayLikeObj, "Martin") === -1 ? false : true); // true​
Another common case is that convert arguments to array as following
// We do not define the function with any parameters, yet we can get all the arguments passed to it​
function doSomething () {
var args = Array.prototype.slice.call (arguments);
console.log (args);
}
doSomething ("Water", "Salt", "Glue"); // ["Water", "Salt", "Glue"]
Borrow other methods
var gameController = {
scores :[20, 34, 55, 46, 77],
avgScore:null,
players :[
{name:"Tommy", playerID:987, age:23},
{name:"Pau", playerID:87, age:33}
]
}
var appController = {
scores :[900, 845, 809, 950],
avgScore:null,
avg :function () {
var sumOfScores = this.scores.reduce (function (prev, cur, index, array) {
return prev + cur;
});
this.avgScore = sumOfScores / this.scores.length;
}
}
// Note that we are using the apply () method, so the 2nd argument has to be an array​
appController.avg.apply (gameController);
console.log (gameController.avgScore); // 46.4​
// appController.avgScore is still null; it was not updated, only gameController.avgScore was updated​
console.log (appController.avgScore); // null​
Use apply() to execute variable-arity function
The Math.max is one example of variable-arity function,
// We can pass any number of arguments to the Math.max () method​
console.log (Math.max (23, 11, 34, 56)); // 56
But what if we have an array of numbers to pass to Math.max? We cannot do this:
var allNumbers = [23, 11, 34, 56];
// We cannot pass an array of numbers to the the Math.max method like this​
console.log (Math.max (allNumbers)); // NaN
This is where the apply () method helps us execute variadic functions. Instead of the above, we have to pass the array of numbers using apply () thus:
var allNumbers = [23, 11, 34, 56];
// Using the apply () method, we can pass the array of numbers:
console.log (Math.max.apply (null, allNumbers)); // 56
The basic difference between Call, Apply and Bind are:
Bind will be used if you want your execution context to come later in the picture.
Ex:
var car = {
registrationNumber: "007",
brand: "Mercedes",
displayDetails: function(ownerName){
console.log(ownerName + ' this is your car ' + '' + this.registrationNumber + " " + this.brand);
}
}
car.displayDetails('Nishant'); // **Nishant this is your car 007 Mercedes**
Let's say i want use this method in some other variable
var car1 = car.displayDetails('Nishant');
car1(); // undefined
To use the reference of car in some other variable you should use
var car1 = car.displayDetails.bind(car, 'Nishant');
car1(); // Nishant this is your car 007 Mercedes
Let's talk about more extensive use of bind function
var func = function() {
console.log(this)
}.bind(1);
func();
// Number: 1
Why? Because now func is bind with Number 1, if we don't use bind in that case it will point to Global Object.
var func = function() {
console.log(this)
}.bind({});
func();
// Object
Call, Apply are used when you want to execute the statement at the same time.
var Name = {
work: "SSE",
age: "25"
}
function displayDetails(ownerName) {
console.log(ownerName + ", this is your name: " + 'age' + this.age + " " + 'work' + this.work);
}
displayDetails.call(Name, 'Nishant')
// Nishant, this is your name: age25 workSSE
// In apply we pass an array of arguments
displayDetails.apply(Name, ['Nishant'])
// Nishant, this is your name: age25 workSSE
call/apply executes function immediately:
func.call(context, arguments);
func.apply(context, [argument1,argument2,..]);
bind doesn't execute function immediately, but returns wrapped apply function (for later execution):
function bind(func, context) {
return function() {
return func.apply(context, arguments);
};
}
Call apply and bind. and how they are different.
Lets learn call and apply using any daily terminology.
You have three automobiles your_scooter , your_car and your_jet which start with the same mechanism (method).
We created an object automobile with a method push_button_engineStart.
var your_scooter, your_car, your_jet;
var automobile = {
push_button_engineStart: function (runtime){
console.log(this.name + "'s" + ' engine_started, buckle up for the ride for ' + runtime + " minutes");
}
}
Lets understand when is call and apply used. Lets suppose that you are an engineer and you have your_scooter, your_car and your_jet which did not come with a push_button_engine_start and you wish to use a third party push_button_engineStart.
If you run the following lines of code, they will give an error. WHY?
//your_scooter.push_button_engineStart();
//your_car.push_button_engineStart();
//your_jet.push_button_engineStart();
automobile.push_button_engineStart.apply(your_scooter,[20]);
automobile.push_button_engineStart.call(your_jet,10);
automobile.push_button_engineStart.call(your_car,40);
So the above example is successfully gives your_scooter, your_car, your_jet a feature from automobile object.
Let's dive deeper
Here we will split the above line of code.
automobile.push_button_engineStart is helping us to get the method being used.
Further we use apply or call using the dot notation.
automobile.push_button_engineStart.apply()
Now apply and call accept two parameters.
context
arguments
So here we set the context in the final line of code.
automobile.push_button_engineStart.apply(your_scooter,[20])
Difference between call and apply is just that apply accepts parameters in the form of an array while call simply can accept a comma separated list of arguments.
what is JS Bind function?
A bind function is basically which binds the context of something and then stores it into a variable for execution at a later stage.
Let's make our previous example even better. Earlier we used a method belonging to the automobile object and used it to equip your_car, your_jet and your_scooter. Now lets imagine we want to give a separate push_button_engineStart separately to start our automobiles individually at any later stage of the execution we wish.
var scooty_engineStart = automobile.push_button_engineStart.bind(your_scooter);
var car_engineStart = automobile.push_button_engineStart.bind(your_car);
var jet_engineStart = automobile.push_button_engineStart.bind(your_jet);
setTimeout(scooty_engineStart,5000,30);
setTimeout(car_engineStart,10000,40);
setTimeout(jet_engineStart,15000,5);
still not satisfied?
Let's make it clear as teardrop. Time to experiment. We will go back to call and apply function application and try storing the value of the function as a reference.
The experiment below fails because call and apply are invoked immediately, hence, we never get to the stage of storing a reference in a variable which is where bind function steals the show
var test_function = automobile.push_button_engineStart.apply(your_scooter);
Syntax
call(thisArg, arg1, arg2, ...)
apply(thisArg, argsArray)
bind(thisArg[, arg1[, arg2[, ...]]])
Here
thisArg is the object
argArray is an array object
arg1, arg2, arg3,... are additional arguments
function printBye(message1, message2){
console.log(message1 + " " + this.name + " "+ message2);
}
var par01 = { name:"John" };
var msgArray = ["Bye", "Never come again..."];
printBye.call(par01, "Bye", "Never come again...");
//Bye John Never come again...
printBye.call(par01, msgArray);
//Bye,Never come again... John undefined
//so call() doesn't work with array and better with comma seperated parameters
//printBye.apply(par01, "Bye", "Never come again...");//Error
printBye.apply(par01, msgArray);
//Bye John Never come again...
var func1 = printBye.bind(par01, "Bye", "Never come again...");
func1();//Bye John Never come again...
var func2 = printBye.bind(par01, msgArray);
func2();//Bye,Never come again... John undefined
//so bind() doesn't work with array and better with comma seperated parameters
JavaScript Call()
const person = {
name: "Lokamn",
dob: 12,
print: function (value,value2) {
console.log(this.dob+value+value2)
}
}
const anotherPerson= {
name: "Pappu",
dob: 12,
}
person.print.call(anotherPerson,1,2)
JavaScript apply()
name: "Lokamn",
dob: 12,
print: function (value,value2) {
console.log(this.dob+value+value2)
}
}
const anotherPerson= {
name: "Pappu",
dob: 12,
}
person.print.apply(anotherPerson,[1,2])
**call and apply function are difference call take separate argument but apply take array
like:[1,2,3]
**
JavaScript bind()
name: "Lokamn",
dob: 12,
anotherPerson: {
name: "Pappu",
dob: 12,
print2: function () {
console.log(this)
}
}
}
var bindFunction = person.anotherPerson.print2.bind(person)
bindFunction()
Call: call invokes the function and allows you to pass arguments one by one
Apply: Apply invokes the function and allows you to pass arguments as an array
Bind: Bind returns a new function, allowing you to pass in a this array and any number of arguments.
var person1 = {firstName: 'Raju', lastName: 'king'};
var person2 = {firstName: 'chandu', lastName: 'shekar'};
function greet(greeting) {
console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}
function greet2(greeting) {
console.log( 'Hello ' + this.firstName + ' ' + this.lastName);
}
greet.call(person1, 'Hello'); // Hello Raju king
greet.call(person2, 'Hello'); // Hello chandu shekar
greet.apply(person1, ['Hello']); // Hello Raju king
greet.apply(person2, ['Hello']); // Hello chandu shekar
var greetRaju = greet2.bind(person1);
var greetChandu = greet2.bind(person2);
greetRaju(); // Hello Raju king
greetChandu(); // Hello chandu shekar
call() :-- Here we pass the function arguments individually, not in an array format
var obj = {name: "Raushan"};
var greeting = function(a,b,c) {
return "Welcome "+ this.name + " to "+ a + " " + b + " in " + c;
};
console.log(greeting.call(obj, "USA", "INDIA", "ASIA"));
apply() :-- Here we pass the function arguments in an array format
var obj = {name: "Raushan"};
var cal = function(a,b,c) {
return this.name +" you got " + a+b+c;
};
var arr =[1,2,3]; // array format for function arguments
console.log(cal.apply(obj, arr));
bind() :--
var obj = {name: "Raushan"};
var cal = function(a,b,c) {
return this.name +" you got " + a+b+c;
};
var calc = cal.bind(obj);
console.log(calc(2,3,4));
Imagine, bind is not available.
you can easily construct it as follow :
var someFunction=...
var objToBind=....
var bindHelper = function (someFunction, objToBind) {
return function() {
someFunction.apply( objToBind, arguments );
};
}
bindHelper(arguments);
function sayHello() {
//alert(this.message);
return this.message;
}
var obj = {
message: "Hello"
};
function x(country) {
var z = sayHello.bind(obj);
setTimeout(y = function(w) {
//'this' reference not lost
return z() + ' ' + country + ' ' + w;
}, 1000);
return y;
}
var t = x('India')('World');
document.getElementById("demo").innerHTML = t;
Use bind for future calls to the function. Both apply and call invoke the function.
bind() also allows for additional arguments to be perpended to the args array.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
In simple terms, all methods are used to set the context(this) explicitly in the regular function
Call: call invokes the function on given context and allows to pass arguments one by one
Apply: apply invokes the function on given context and allows to pass arguments as an array
Bind: bind returns a new function by setting the provided context, and allows to pass arguments one by one
Notes:
Call and Apply both are similar only difference is the way they expect arguments
The mentioned methods do not work with arrow function
The first difference between call(), apply(), and bind() methods in JavaScript is their time of execution!
call() and apply() being similar are executed instantly, whereas, bind() creates a new function which we have to explicitly call at any later point of time!
Another difference is, that while passing arguments, call() allows us to pass one by one separated by commas, apply() allows us to pass as an array of arguments, and bind() allows us to do both!
I have attached the example code below!
const person = {
fullName : function (randomMessage) {
return `Hello, ${this.firstName} ${this.lastName} ${randomMessage}`;
}
}
const personOne = {
firstName : "John",
lastName : "Doe"
}
const personTwo = {
firstName : "Jack",
lastName : "Adhikari"
}
let fullNameBind = person.fullName.bind(personOne, "--Binding");
let fullNameCall = person.fullName.call({firstName : "Sarah", lastName: "Holmes"}, "--Calling");
let fullNameApply = person.fullName.apply(personTwo, ["--Applying"]);
console.log(fullNameBind());
console.log(fullNameCall);
console.log(fullNameApply);
I think the same places of them are: all of them can change the this value of a function.The differences of them are: the bind function will return a new function as a result; the call and apply methods will execute the function immediately, but apply can accept a array as params,and it will parse the array separated.And also, the bind function can be Currying.
bind function should be use when we want to assign a function with particular context for eg.
var demo = {
getValue : function(){
console.log('demo object get value function')
}
setValue : function(){
setTimeout(this.getValue.bind(this),1000)
}
}
in above example if we call demo.setValue() function and pass this.getValue function directly then it doesn't call demo.setValue function directly because this in setTimeout refers to window object so we need to pass demo object context to this.getValue function using bind. it means we only passing function with the context of demo object not actully calling function.
Hope u understand .
for more information please refer
javascript bind function know in detail

How to bind an argument to a jquery callback without affecting this

I'm new to javascript/jquery and here's the example code I need help with:
function add(text) {
$(this).replaceWith('<label>'+text+'</label>');
}
var label = 'Added';
$('#myDiv').append($('<button type="button">Add</button>').click(function() {
add.call(this, label);
}));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="myDiv"></div>
Is there a "better" way of setting the click callback here?
If the add function did not have a text argument, I could have easily used .click(add) and the button will be bound automatically as this.
But with the argument, I can't bind text without having to set the value of this too i.e. .click(add.bind(this, label)) would be wrong as this is set to the global context.
Thoughts?
As Andreas points out in a comment, there's a solution to this that's specific to jQuery event handlers: The data argument to the on function.
More generally, though, what you're looking for is sometimes called "currying" (or "partial application;" purists tell me one of them is technically incorrect but I can never remember which).
I have a function I use for that which I add to Function.prototype; it looks like this (see comments):
(function() {
var slice = Array.prototype.slice;
Object.defineProperty(Function.prototype, "curry", {
value: function() {
// Remember the original function and the arguments we wre called with
var f = this,
curried = slice.call(arguments);
// Return a new function
return function() {
// Our function was called, add in any arguments it was called with...
var args = curried.concat(slice.call(arguments));
// ...and call the original, passing along `this`
return f.apply(this, args);
};
}
});
})();
In your case, you'd use it like this:
var label = 'Added';
$('#myDiv').append($('<button type="button">Add</button>').click(add.curry(label)));
Note that your add function will be called with the value of label (as it was when we made the curry call, not as it is later), followed by any arguments that the curried function was called with (e.g., the event object).
Example:
(function() {
var slice = Array.prototype.slice;
Object.defineProperty(Function.prototype, "curry", {
value: function() {
// Remember the original function and the arguments we wre called with
var f = this,
curried = slice.call(arguments);
// Return a new function
return function() {
// Our function was called, add in any arguments it was called with...
var args = curried.concat(slice.call(arguments));
// ...and call the original, passing along `this`
return f.apply(this, args);
};
}
});
})();
function add(text) {
console.log("add called with text = '" + text + "'");
}
var label = 'Added';
$('#myDiv').append($('<button type="button">Add</button>').click(add.curry(label)));
<div id="myDiv"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Make object's properties available inside function

I would like to do the following.I have a code like this:
var obj = {
method : function() {}
};
var func = function() {
return method(); //method is undefined here
};
func(); // What to do here?
Is it possible to call func in a way that it will see the method inside from obj as it was given for example as a parameter. I want to use obj.method inside func, without writing 'obj.' before and without modifying func itself. Is there any hack possible to achieve this?
In other words, is it possible to force obj as a closure into func?
I tried:
with(obj) {
func();
}
But it doesn't work. Anyone, any ideas? Or is it the only option to get the body of the function as string, put 'with(obj)' inside it and then create a new function out of it?
Clarification:
Because this code will be in a helper class 'eval' is OK. Which I don't want is the modification of the function through .toString(), because browsers implement it differently.
This is a solution, using eval (MDN):
var obj = {
method : function() {console.log("it workes!");}
};
var func = function() {
return method(); //method is undefined here
};
var newfunc = (function (obj, func) {
var method = obj.method;
eval("var f = " + func.toString());
return f;
}(obj, func));
newfunc(); //it workes
Basically you're just creating a new scope with a local variable called method and re-evaluating the function body in this scope. So you're basically creating a new function with the same body. I don't really like this approach and I wouldn't recommend it, but considering your constraints, it might be the only solution.
And yes, it still requires you to write obj.method, but not inside of func. So I figured, it should be ok.
EDIT
So here is a version, in which you don't have to specify the property name manually:
var newfunc = (function (__obj__, __func__) {
for (var __key__ in __obj__) {
if (__obj__.hasOwnProperty(__key__)) {
eval("var " + __key__ + " = " + __obj__[__key__]);
}
}
eval("var __f__ = " + func.toString());
return __f__;
}(obj, func));
This also done by using eval().
Note that I changed all remaining local variables to a names containing underscores, to minimize the probability of name collisions with properties inside obj.
Note also that not all valid property names are valid variable names. You could have an object like this:
var obj = {
"my func": function () {}
}
But if you would use this object you would generate a syntax error with the above method, because it would try to evaluate:
var my func = ...
As apsillers said in the comment section, it gets even worse if you don't have control over the properties of obj. In this case you shouldn't use eval at all, because you would make cross-site scripting attacks very easy (example from apsillers):
var obj = {
"a; alert('xss'); var b": function () {}
}
would evaluate to 3 different statements:
var a;
alert('xss');
var b = function () {};
This is not possible unless you define method separately:
var obj = {
method : function() {}
},
method = obj.method;
// rest of code
This is because the method reference inside func() assumes the window. namespace; thus, without modifying func() itself, it can't be done sanely.
More clarified version based on basilikum's answer, and I've found a simplification with 'with':
var obj = {
method : function() { return "it workes!"; }
};
var func = function() {
return method(); //method is undefined here
};
(function (obj, func) {
with(obj) {
eval("var __res__ = (" + func.toString() + ")()");
}
return __res__;
}(obj, func));
>> "It workes!"

How do I set a callback function parameter like 'data' in the "jQuery.ajax({ success : function(data)"?

I am wondering how to set the first parameter of a callback function to what I want, the same way jquery does in the success callback or the complete callback
I want to do this:
$.ajax({
success: function(data) {
alert(data)
}
});
from what I understand this is as close as I can get to what I want
function test(text) {
this.text = text
this.success = function(this.text) { }
}
var a = new test('King Kong')
a.success = function(k){
alert(k)
}
and I want the alert to say "King Kong"
Here's an example of accepting a callback in your constructor function and then calling it later in response to some trigger. In the below, the trigger is someone calling the trigger function, but it can be anything you want:
function Test(text, callback) {
this.text = text;
this.success = callback;
}
Test.prototype.trigger = function() {
// Call the success callback, passing in the text
this.success(this.text);
};
var a = new Test('King Kong', function(k) {
alert(k);
});
a.trigger();
(I've made Test initially-capped there. That's the convention for constructor functions, which you are of course free to ignore.)
The key, fundamental thing to understand is that functions are just objects like anything else. You can pass references to them around, etc. To call a function, you just access whatever variable you have the function reference stored in and add parentheses (optionally with the function's arguments in the parentheses).
Consequently, all of the following call the foo function and trigger the alert:
function foo(msg) {
alert(msg);
}
var f = foo; // No parens, just getting the function reference, not calling it
f("Hi there"); // Now we're calling it
var a = {};
a.nifty = f;
a.nifty("Hi again");
function bar(func) {
func("Hello for the third time");
}
bar(foo); // Passing a reference to `foo` into the `bar` function, which will call it
Advanced: Now, one thing that jQuery does is that it calls the callback with the this value set to something specific (usually the DOM element related to the call). That will happen any time you call a function via an object property:
var a = {name: "Fred"};
a.func = function() {
alert(this.name);
};
a.func(); // alerts "Fred"
...but that's not the only way you can do it; there's also the call and apply functions on the function object itself:
var a = {name: "Fred"};
function func() {
alert(this.name);
}
func.call(a); // alerts "Fred"
There, the function isn't assigned to any of a's properties, but we've called the function using call, which accepts the value for this as its first argument. Call also passes on any further arguments to the function you're calling:
function func(msg1, msg2) {
alert(this.name + " says " + msg1 + " and " + msg2);
}
var a = {name: "Fred"};
func.call(a, "one", "two"); // alerts "Fred says one and two"
apply does exactly the same thing, but it accepts the arguments to pass on to the underlying function as an array instead of as discrete arguments:
function func(msg1, msg2) {
alert(this.name + " says " + msg1 + " and " + msg2);
}
var a = {name: "Fred"};
func.apply(a, ["one", "two"]); // alerts "Fred says one and two"
// ^------------^----- note these args are now an array
More reading: Mythical Methods
I figured out what I was looking for, it was this
function Test(data)
{
data.success(data.text)
}
var a = new Test({
text : 'DATA',
success : function(k) {
alert(k)
}
})
or
function Test()
{
this.setText = function(k) {
this.text = k
}
this.setCall = function(k) {
this.call = k
this.call(this.text)
}
}
var a = new Test
a.setText('DATA')
a.setCall(function(k) {
alert(k)
})
both alert "DATA"

Categories

Resources