I'm actually studying Crockford's Javascript: the good parts. I am new to JavaScript so I'm having a difficult time to understand how this code works:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Here's what I think:
Being a method (a function inside an object), this
points to the Function
object, but why the need to return the object since i'm having access on it from inside the method? If i am right, this
is a reference, not a local copy, so:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
};
Should work as well.
From the other side, in JavaScript a function without a return statement returns undefined
and assign it to Function.prototype.method
.
What's the point of returning this
?
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
var add = function(a, b) {
return a+b;
};
Function.method('add', add);
var f = function() {};
print(f.add(1,2));
Number.method('integer', function () {
return Math[this < 0 ? 'ceil' : 'floor'](this);
});
print((-10/3).integer());
Output:
-3 3
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
};
var add = function(a, b) {
return a+b;
};
Function.method('add', add);
var f = function() {};
print(f.add(1,2));
Number.method('integer', function () {
return Math[this < 0 ? 'ceil' : 'floor'](this);
});
print((-10/3).integer());
Output:
-3 3
Use an intersection type to extend a type in TypeScript, e.g. type TypeB = TypeA & {age: number;} . Intersection types are defined using an ampersand & and are used to combine existing object types. You can use the & operator as many times as necessary to construct a type.
js. init = extendFunction(init, function(args) { doSomethingHereToo(); }); But in your specific case, it's easier to extend the global onload function: extendFunction('onload', function(args) { doSomethingHereToo(); });
The extends keyword is used in class declarations or class expressions to create a class that is a child of another class.
Array, Map, and other built-in classes are extendable. The most impressive thing is that built-in methods such as map , filter, and more - return new objects of literally the inherited type NumsArray .
let me try to explain it. I didn't read that book, but an article Classical Inheritance in JavaScript of Douglas Crockford has one important sentence, related to that example about Function.prototype.method:
It returns this. When I write a method that doesn't need to return a value, I usually have it return this. It allows for a cascade-style of programming.
actually I am not familiar with that term, I think well known term is "Fluent Interface" or "Method Chaining", read that wiki page, there are examples in different languages, so you will understand it..
PS. @Gianluca Bargelli was a bit faster to provide example of using Function.prototype.method this way, so I don't post it in my answer
ADDON: how you can use it in terms of your example:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
}
Number.method('integer', function () { // you add 'integer' method
return Math[this < 0 ? 'ceil' : 'floor'](this);
})
.method('square', function () { // you add 'square' method with help of chaining
return this * this;
});
console.info( (-10/3).integer().square() ); // <- again chaining in action
you see, integer() returns Number object, so you can call another method, instead of writing:
var a = (-10/3).integer();
console.info( a.square() );
and few words about my way of using it, most of time I prefer to write "each method - new line with indent, for me this way is more readable:
Function.method('add', add)
.method('sub', sub)
.method('mul', mul)
.method('div', div);
this way I see where I start, and "new line/indent" tell me that I still modify that object. Compare it to long line:
Function.method('add', add).method('sub', sub).method('mul', mul).method('div', div);
or typical approach:
Function.method('add', add);
Function.method('sub', sub);
Function.method('mul', mul);
Function.method('div', div);
ADDON2: Usually I use this approach (Fluent interface pattern) when I work with entities e.g. Java code:
public class Person {
private String name;
private int age;
..
public String getName() {
return this.name;
}
public Person setName( String newName ) {
this.name = newName;
return this;
}
public int getAge() {
return this.age;
}
public Person setAge( int newAge ) {
this.age = newAge;
return this;
}
..
}
it allows me to construct Person
object in easy way:
Person person = new Person().setName("Leo").setAge(20);
Some people make it a bit different, they add new kind of methods to set
/get
, and call it with
:
public class Person {
private String name;
private int age;
..
public String getName() {
return this.name;
}
public void setName( String newName ) {
this.name = newName;
}
public Person withName( String newName ) {
this.setName( newName ); // or this.name = newName; up to you
return this;
}
public int getAge() {
return this.age;
}
public void setAge( int newAge ) {
this.age = newAge;
}
public Person withAge( int newAge ) {
this.setAge( newAge ); // or this.age = newAge; up to you
return this;
}
..
}
Now my previous example looks like:
Person person = new Person().withName("Leo").withAge(20);
This way we don't change meaning of set method (I mean we do not enhance it, so it work as most of developers expect... at least that people do not expect that set
method can return anything ;) ). One interesting thing about these special methods - they can loose their self-documenting, but they improve readability when you use them (like in example with Person
creation, withName
tells very well what exactly we are doing..
to read more:
FluentInterface - Martin Fowler's description of that pattern
Fluent Interfaces in PHP
The Weekly Source Code 14 - Fluent Interface Edition - as for me short and good enough to see pros and cons (as well as links to other resources)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With