function theFunction(name, profession) {console.log("My name is " + name + " and I am a " + profession +".");}theFunction("John", "fireman");theFunction.apply(undefined, ["Susan", "school teacher"]);theFunction.call(undefined, "Claude", "mathematician");theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator
f.call(thisObject, a, b, c); // Fixed number of arguments
f.apply(thisObject, arguments); // Forward this function's arguments
var args = [];while (...) {args.push(some_value());}f.apply(thisObject, args); // Unknown number of arguments
var obj = {};obj.value = 10;/** @param {...number} additionalValues */obj.addValues = function(additionalValues) {for (var i = 0; i < arguments.length; i++) {this.value += arguments[i];}return this.value;};// Evaluates to 30 because obj is used as the value for 'this' when// obj.addValues() is called, so obj.value becomes 10 + 20.obj.addValues(20);
var f = obj.addValues;// Evaluates to NaN because window is used as the value for 'this' when// f() is called. Because and window.value is undefined, adding a number to// it results in NaN.f(20);// This also has the unintentional side effect of adding a value to window:alert(window.value); // Alerts NaN
/*** @param {*=} receiver to substitute for 'this'* @param {...} parameters to use as arguments to the function*/Function.prototype.call;/*** @param {*=} receiver to substitute for 'this'* @param {Array} parameters to use as arguments to the function*/Function.prototype.apply;
// When f is called with obj as its receiver, it behaves the same as calling// obj.addValues(). Both of the following increase obj.value by 60:f.call(obj, 10, 20, 30);f.apply(obj, [10, 20, 30]);
function makeClass( properties ) {var ctor = properties['constructor'] || function(){}var Super = properties['extends'];var Class = function () {// Here 'call' cannot work, only 'apply' can!!!if(Super)Super.apply(this,arguments);ctor.apply(this,arguments);}if(Super){Class.prototype = Object.create( Super.prototype );Class.prototype.constructor = Class;}Object.keys(properties).forEach( function(prop) {if(prop!=='constructor' && prop!=='extends')Class.prototype[prop] = properties[prop];});return Class;}
//Usagevar Car = makeClass({constructor: function(name){this.name=name;},yourName: function() {return this.name;}});//We have a Car class nowvar carInstance=new Car('Fiat');carInstance.youName();// ReturnsFiat
var SuperCar = makeClass({constructor: function(ignore,power){this.power=power;},extends:Car,yourPower: function() {return this.power;}});//We have a SuperCar class now, which is subclass of Carvar superCar=new SuperCar('BMW xy',2.6);superCar.yourName();//Returns BMW xysuperCar.yourPower();// Returns 2.6
function Person(name) {this.name = name;}Person.prototype.getName = function(a,b) {return this.name + " " + a + " " + b;}
var reader = new Person('John Smith');
reader.getName = function() {// Apply and Call executes the function and returns value
// Also notice the different ways of extracting 'getName' prototypevar baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]);console.log("Apply: " + baseName);
var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy");console.log("Call: " + baseName);
// Bind returns function which can be invokedvar baseName = Person.prototype.getName.bind(this, "is a", "boy");console.log("Bind: " + baseName());}
reader.getName();/* OutputApply: John Smith is a boyCall: John Smith is a boyBind: John Smith is a boy*/
// min/max number in an arrayvar numbers = [5, 6, 2, 3, 7];
// using Math.min/Math.max applyvar max = Math.max.apply(null, numbers);// This about equal to Math.max(numbers[0], ...)// or Math.max(5, 6, ...)
var min = Math.min.apply(null, numbers)
let obj = {val1: 5,val2: 10}
const summation = function (val3, val4) {return this.val1 + this.val2 + val3 + val4;}
console.log(summation.apply(obj, [2 ,3]));// first we assign we value of this in the first arg// with apply we have to pass in an array
console.log(summation.call(obj, 2, 3));// with call we can pass in each arg individually
var name = 'unwantedGlobalName';
const obj = {name: 'Willem',sayName () { console.log(this.name);}}
let copiedMethod = obj.sayName;// we store the function in the copiedmethod variable
copiedMethod();// this is now window, unwantedGlobalName gets logged
copiedMethod.call(obj);// we enforce this to be obj, Willem gets logged
func.call(context, args1, args2 ); // pass arguments as "," separated value
func.apply(context, [args1, args2]); // pass arguments as "Array"
我们还使用“Call”和“Ap唱”方法来更改参考,如下面的代码所定义
let Emp1 = {name: 'X',getEmpDetail: function(age, department) {console.log(`Name: ${this.name} Age: ${age} Department: ${department}`)}}
Emp1.getEmpDetail(23, 'Delivery')
// 1st approach of changing "this"let Emp2 = {name: 'Y',getEmpDetail: Emp1.getEmpDetail}
Emp2.getEmpDetail(55, 'Finance')
// 2nd approach of changing "this" using "Call" and "Apply"let Emp3 = {name: 'Emp3_Object',}
Emp1.getEmpDetail.call(Emp3, 30, 'Admin')
// here we have change the ref from **Emp1 to Emp3** object// now this will print "Name = Emp3_Object" because it is pointing to Emp3 objectEmp1.getEmpDetail.apply(Emp3, [30, 'Admin'])
var car = {name: "Reno",country: "France",showBuyer: function(firstName, lastName) {console.log(`${firstName} ${lastName} just bought a ${this.name} from ${this.country}`);}}
const firstName = "Bryan";const lastName = "Smith";
car.showBuyer(firstName, lastName); // Bryan just bought a Reno from France
const obj = { name: "Maserati", country: "Italy" };
car.showBuyer.call(obj, firstName, lastName); // Bryan Smith just bought a Maserati from Italy
car.showBuyer.apply(obj, [firstName, lastName]); // Bryan Smith just bought a Maserati from Italy