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
Nested Routes with React Router V4/V5
Detecting When User Scrolls to Bottom of Div with Jquery
Object.Watch() for All Browsers
How to Get JSON from Url in JavaScript
How to Post a X-Www-Form-Urlencoded Request Using Fetch
How to Find Out What Character Key Is Pressed
Identifying Between Refresh and Close Browser Actions
Function Declarations Inside If/Else Statements
JavaScript - Arrow Functions This in Event Handler
Firestore Update Single Item in an Array Field
Assigning Prototype Methods *Inside* the Constructor Function - Why Not
Jquery Get Specific Option Tag Text
Why Is Mutating the [[Prototype]] of an Object Bad for Performance
Code Within D3.JSON() Callback Is Not Executed