I'm relatively new to JavaScript and I would like to know when it is okay to chain JavaScript methods and when not, and what is the reason when you can't....
I'm creating an element and want to assign a class-name and then put some text inside the element. But for some reason you can't chain these methods. Ideally I would do something like this:
var li = document.createElement("li").classList.add("className").innerHTML = "Some string";
I kind of understand why you can't chain the final part, because you can't assign twice. But I can't even chain the second method, instead I have to do this:
var li = document.createElement("li");
li.classList.add("className");
li.innerHTML = "Some string";
Why is that?
I'm relatively new to JavaScript and I would like to know when it is okay to chain JavaScript methods and when not, and what is the reason when you can't....
I'm creating an element and want to assign a class-name and then put some text inside the element. But for some reason you can't chain these methods. Ideally I would do something like this:
var li = document.createElement("li").classList.add("className").innerHTML = "Some string";
I kind of understand why you can't chain the final part, because you can't assign twice. But I can't even chain the second method, instead I have to do this:
var li = document.createElement("li");
li.classList.add("className");
li.innerHTML = "Some string";
Why is that?
Share Improve this question asked Nov 3, 2016 at 11:03 AndrewRMillarAndrewRMillar 6621 gold badge7 silver badges21 bronze badges 1- If the later method can be applied on the return type of the first method then you can chain the methods, otherwise not. – void Commented Nov 3, 2016 at 11:05
5 Answers
Reset to default 3Chaining isn't anything special. It's just using the return value of a function. If a function returns an object that has a method on it, then you can use that method by calling it directly on the result of calling the function. That is,
foo().bar();
...works if foo
returns an object that has a method called bar
.
You can't do what you've shown in your first code block because:
add
doesn't return anything, so the result of calling it isundefined
.- If
add
did return something, it almost certainly wouldn't be the elementcreateElement
created. (It probably should return a reference to theDOMTokenList
you called it on, but it doesn't.) - And even if it did, the result of an assignment operation (
innerHTML = ...
) is the value that was assigned, not a reference to the element.
Side note: If you like chaining APIs, look at using jQuery. It lets you do this:
var li = $("<li>").addClass("className").html("Some string");
...because most of its API methods return the jQuery instance that they were called on or another useful jQuery instance if not (and $()
returns the set containing the single element outermost element it creates in the $("<li>")
example). The API is specifically designed with chaining in mind. The DOM API is not.
It depends on the return value of the function. In your case the li.classList
is an attribute, not a function returning the method itself. Thus you cannot chain it.
Chaining depends on return type of called function
document.createElement("li")
will return a HTML element which has property called classList
.classList
will return a DOMTokenList. This in turn has property .add
. But .add
does not return anything. Hence you cannot call .innerHTML
document.createElement("li").classList.add("className").innerHTML = "Some string";
Sample
var element = document.createElement("li");
console.log(element)
var classList = element.classList
console.log(classList)
var add = classList.add('dummy');
console.log(add)
In order to use chaining the last method must return a value. If you want to create an instance of an object, every method must return the this object.
var Dog= function() {
this.name = 'Buck';
this.color = 'brown';
};
Dog.prototype.setName = function(name) {
this.name = name;
return this;
};
Dog.prototype.setColor = function(color) {
this.color = color;
return this;
};
So with chaining it will look like this
new Dog()
.setName('Bob')
.setColor('black')
li.classList.add("className");
this line doesn't return an object (a result of li.classList
or simply li
for instance), instead it returns undefined
as per this doc: http://www.javascripture./DOMTokenList . Thus, you cannot call any methods on the result.