Thursday 24 November 2016

Effective Java Item 35. Write own annotation and reflection

 //Almost always RUNTIME  
 @Retention(RetentionPolicy.RUNTIME)  
 @Target({ElementType.TYPE, ElementType.METHOD})  
 @interface MyTest {}  
 class Sample{  
   @MyTest  
   public static void m1(){}  
 }  
 public class MyAnnotation{  
   public static void main(String[] args){  
     Class testClass = Sample.class;  
     //Get all methods including private, protected  
     //as opposed to testClass.getMethods() only returning public methods  
     for (Method m : testClass.getDeclaredMethods()){  
       if (m.isAnnotationPresent(MyTest.class)){  
         try{  
           m.invoke(null); //Call static method  
         } catch (InvocationTargetException e) {  
           e.printStackTrace();  
         } catch (Exception e) {  
           e.printStackTrace();  
         }  
       }  
     }  
   }  
 }  

Javascript: check undefined/null

If you are sure the variable has been declared (i.e var a;), simply use
if (a != null){
    ...
}
If a can be undeclared, then use


if (typeof a != 'undefined' && a != null){
    ...
}

Javascript: softbind

Excerpted from You Don't Know JS: this & Object Prototypes

I couldn't fully understand the code below.
  
if (!Function.prototype.softBind) {
    Function.prototype.softBind = function(obj) {
        var fn = this,
            curried = [].slice.call( arguments, 1 ),
            bound = function bound() {
                return fn.apply(
                    (!this ||
                        (typeof window !== "undefined" &&
                            this === window) ||
                        (typeof global !== "undefined" &&
                            this === global)
                    ) ? obj : this,
                    curried.concat.apply( curried, arguments )
                );
            };
        bound.prototype = Object.create( fn.prototype );
        return bound;
    };
}

function foo() {
   console.log("name: " + this.name);
}

var obj = { name: "obj" },
    obj2 = { name: "obj2" },
    obj3 = { name: "obj3" };

var fooOBJ = foo.softBind( obj );

fooOBJ(); // name: obj

obj2.foo = foo.softBind(obj);
obj2.foo(); // name: obj2   <---- look!!!

fooOBJ.call( obj3 ); // name: obj3   <---- look!

setTimeout( obj2.foo, 10 ); // name: obj   <---- falls back to soft-binding
  1. What does [].slice.call(...) do? 
  2. Are the two 'this' referring to the same thing? 
  3. What does bound.prototype = Object.create(fn.prototype) do?
Let's go through the code step by step by inserting some console output code. And for the sake of demonstrating the purpose of curried, I also rewrote the foo() function.
if (!Function.prototype.softBind) {
    Function.prototype.softBind = function(obj) {
        var fn = this;
        console.log("Outer this = "+ fn);
        var curried = [].slice.call( arguments, 1 );
        console.log("Outer curry = "+curried);
        var bound = function bound() {
            console.log("Inner this = " + this);
            console.log("Inner curry = "+curried.concat.apply( curried, arguments ));
            return fn.apply(
                (!this ||
                    (typeof window !== "undefined" &&
                        this === window) ||
                    (typeof global !== "undefined" &&
                         this === global)
                ) ? obj : this,
                curried.concat.apply( curried, arguments )
            );
        };
        bound.prototype = Object.create( fn.prototype );
        console.log("return bound");
        return bound;
    };
}

function foo(a1, a2) {
   console.log(a1 + ' ' +a2 + " name: " + this.name);
}

var obj = { name: "obj" },
    obj2 = { name: "obj2" },
    obj3 = { name: "obj3" };

var fooOBJ = foo.softBind( obj, 'A1');
fooOBJ('A2'); // name: obj

//obj2.foo = foo.softBind(obj, 'A1');
//obj2.foo('A2'); // name: obj2   <---- look!!!

//fooOBJ.call( obj3 ); // name: obj3   <---- look!
Here is the output.
Outer this = function foo(a1, a2) {
   console.log(a1 + ' ' +a2 + " name: " + this.name);
}
Outer curry = A
return bound
Inner this = [object Object]
Inner curry = A,A2
A A2 name: obj2

[].slice.call(arguments, 1)
is semantically equal to
arguments.slice(1)
except the latter is syntactically incorrect because the variable arguments is not a real array. It's an 'array-like' object.

The outer this refers to the foo function while the inner this refers to the window (global) variable. It's worth noting that by the time foo.softBind(obj) completes execution, the bound() function hasn't been invoked. It's only invoked when the line fooOBJ('A2') is executed.

bound.prototype = Object.create( fn.prototype );
copies all the properties of foo to bound, essentially ensuring that after softbind the function foo doesn't lose any properties.