0

function.apply does not register the first argument (index 0) in my array.

I have tried the rest/spread syntax, and the code below seems to work fine:

let sayName = function (object, ...languages) {
    console.log(`My name is ${this.name} and I speak ${languages.join(', ')}`);
};

let stacy = {
    name: 'Stacy',
    age: 34
};

let languages = ['Javascript', 'CSS', 'German','English', 'Spanish'];
sayName(stacy, ...languages);

But the code below does not work, with explicit binding function.apply:

let languages1 = ['Javascript', 'CSS', 'German','English', 'Spanish'];
sayName.apply(stacy, languages1) 

The result always leaves out the 0 index from the array, i.e. "Javascript" is not included in the output.

What am I doing wrong?

1
  • 2
    The first argument you pass to apply is used as the this object assignment. It is not passed as argument to your function. All that is in the documentation of apply. Since you reference this in your function, just remove the object parameter from your function header. Commented Feb 16, 2019 at 9:27

1 Answer 1

3

Your function seems to expect an object parameter, but that is incorrect seeing how you call it with apply. When you call apply or call, the first argument to that method is used to set the this value for your function's execution context. It does not get passed as argument.

As your function references this, it is important that you set this correctly, and so the use of apply or call is the good choice.

So change:

let sayName = function (object, ...languages) {

to:

let sayName = function (...languages) {

Note that you didn't use object anyway in your function's code.

In the version where you don't call apply, but call the function directly, you do:

sayName(stacy, ...languages);

...but here the this object will not be set correctly. You should have used call to ensure that this will refer to stacy:

sayName.call(stacy, ...languages);

Check out the documentation of apply:

Syntax

function.apply(thisArg, [argsArray])

Parameters

thisArg

Optional. The value of this provided for the call to func. [...]

argsArray

Optional. An array-like object, specifying the arguments with which func should be called. [...]

Object oriented programming, a better way

Now, taking a step back you should really have defined sayName as a prototype method, and construct stacy like so:

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    sayName(...languages) {
        console.log(`My name is ${this.name} and I speak ${languages.join(', ')}`);
    }
}

let stacy = new Person('Stacy', 34);
let languages = ['Javascript', 'CSS', 'German','English', 'Spanish'];
stacy.sayName(...languages);

... and why not actually store the languages a person speaks as a property as well, and remove the console.log from the method, as it should be the caller who decides to where the output should be made (maybe to a file or to a HTML element):

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
        this.languages = [];
    }
    speaks(...languages) {
        this.languages = languages;
    }
    introduction() {
        return `My name is ${this.name} and I speak ${this.languages.join(', ')}`;
    }
}

let stacy = new Person('Stacy', 34);
stacy.speaks('Javascript', 'CSS', 'German','English', 'Spanish');
console.log(stacy.introduction());

Sign up to request clarification or add additional context in comments.

1 Comment

A great example for me to delve into and look at the documentation more. Thanks alot

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.