JavaScript Function Aliasing Doesn't Seem to Work

JavaScript function aliasing doesn't seem to work

You have to bind that method to the document object. Look:

>>> $ = document.getElementById
getElementById()
>>> $('bn_home')
[Exception... "Cannot modify properties of a WrappedNative" ... anonymous :: line 72 data: no]
>>> $.call(document, 'bn_home')
<body id="bn_home" onload="init();">

When you’re doing a simple alias, the function is called on the global object, not on the document object. Use a technique called closures to fix this:

function makeAlias(object, name) {
var fn = object ? object[name] : null;
if (typeof fn == 'undefined') return function () {}
return function () {
return fn.apply(object, arguments)
}
}
$ = makeAlias(document, 'getElementById');

>>> $('bn_home')
<body id="bn_home" onload="init();">

This way you don’t loose the reference to the original object.

In 2012, there is the new bind method from ES5 that allows us to do this in a fancier way:

>>> $ = document.getElementById.bind(document)
>>> $('bn_home')
<body id="bn_home" onload="init();">

Why doesn't JavaScript function aliasing work?

Yes, you should persist the context :

var log;

if (window.console && typeof console.log === "function"){
// use apply to preserve context and invocations with multiple arguments
log = function () { console.log.apply(console, arguments); };
} else {
log = function(){ return; }
}

What is happening is that the context (the this value), is implicitly set when you call a function, for example:

var obj = {
method: function () { return this; }
};

obj.method() === obj; // true

In this case, you are calling a function that is defined as a property of an object, when the function is invoked, the this value is set to that object.

Now as in your example, if you copy a reference of that method to a variable:

var method = obj.method;
method() === window; // global object

As you can see, the this value refers to the global object.

So, to avoid this implicit behavior you can set the context explicitly, with the call or apply functions.

Javascript function aliasing without .apply

You can use the new ECMAScript 5 .bind() method. An alternative implementation for browsers that don't support it (taken from the MDC documentation I linked to):

// Function.prototype.bind polyfill
if ( !Function.prototype.bind ) {

Function.prototype.bind = function( obj ) {
if(typeof this !== 'function') // closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');

var slice = [].slice,
args = slice.call(arguments, 1),
self = this,
nop = function () {},
bound = function () {
return self.apply( this instanceof nop ? this : ( obj || {} ),
args.concat( slice.call(arguments) ) );
};

bound.prototype = this.prototype;

return bound;
};
}

Why can't one set an alias to document.getElementById()?

When you call foo.bar() then this is set to foo inside bar
When you copy foo.bar to window.bar then call window.bar(), this is set to window.

getElementById has to operate on a DOM document object.

Document method reference is not worked in JavaScript

Because this in JavaScript is determined in runtime.

document.querySelector(...) // this -> document

let qs = document.querySelector

qs(...) // In this case `this` refer to the global object, which is window in a browser

You need to bind this when you created a function reference.

let qs = document.querySelector.bind(document)

Or giving a this binding when you call it.

qs.call(document, 'button')

In Javascript, is it true that function aliasing works as long as the function being aliased doesn't touch this ?

Basically yes, however, in JavaScript functions are first class objects, so there it is not really aliasing. What you are doing is assigning the value of a variable to another variable, an in this case the value just happens to be a function.

The magic this variable however is a little bit different. In JavaScript methods are not bound to a class or an object, like they are in most other languages. When you call a method the this is set by the dot operator, or by the apply or call methods. It works like this:

var i = 1;
var f = function () { alert(this.i); }
f(); // in a browser, alerts 1, because this will be window if it isn't anything else.

var obj = { i: 10 };
obj.g = f;
obj.g(); // alerts 10, because the dot binds this to obj

var other_obj = { i: 23 };
f.apply(g); // alerts 23, because now apply binds this to other_obj

You can bind methods to objects by using closures:

var f = function () { alert(this.i); }
var obj = { i: 10 };

obj.m = function () { f.apply(obj); }
obj.m(); // alerts 10

var g = obj.m;
g(); // alerts 10, because now the closure is called, which binds this correctly.

Node-Canvas image anti-aliasing doesn't seem to work

When upscaling patterns, cairo uses bilinear interpolation by default, which should look reasonable. However, when downscaling, cairo currently (as of 1.12.14) does not properly antialias patterns. There is no way to get this, short of actually adding the feature to cairo itself, though see below for a potential workaround.

The 'antialias' setting in cairo controls the antialiasing of rasterized shapes and text, not patterns. The setting that controls antialiasing for patterns is called 'cairo_pattern_set_filter' and has the following values:

CAIRO_FILTER_FAST,             // usually the same as NEAREST
CAIRO_FILTER_GOOD, // usually the same as BILINEAR
CAIRO_FILTER_BEST, // usually the same as BILINEAR
CAIRO_FILTER_NEAREST, // for upscaling, this is pixel-replication
CAIRO_FILTER_BILINEAR, // for upscaling, this is linear interpolation
CAIRO_FILTER_GAUSSIAN // not implemented, should not be used

But as mentioned, none of them work well for downscaling.

A workaround that some people have used is to scale the image down in steps of 2. That is, keep downscaling the image to half the size in both dimensions until it is roughly the desired size. This downscaled image can then be used with a modified transformation that downscales by less than 2.

Make alias to document.getElementById in Javascript

Possibly the easiest/shortest way:

function $(id) { return document.getElementById(id); };

Why isn't RequireJS passing jQuery into the functions alias?

jQuery should be loaded through the special name "jquery", otherwise it won't register itself (since jQuery uses a named define).

// create an alias that points to proper file
require.config({
paths : {
jquery : "http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min"
}
});

// require jquery usign the path config
require(["jquery"], function ($) {
console.log($);
});

That is the main reasons why named define is considered an anti-pattern and should be used only when needed (when you have multiple modules inside same file).



Related Topics



Leave a reply



Submit