JavaScript 함수 앨리어싱이 작동하지 않는 것 같습니다.
이 질문을 읽고 있었고 함수 래퍼 방법이 아닌 별칭 방법을 시도하고 싶었지만 Firefox 3 또는 3.5beta4 또는 Google Chrome에서 디버그 창과 둘 다에서 작동하도록 할 수 없었습니다. 테스트 웹 페이지에서.
개똥 벌레:
>>> window.myAlias = document.getElementById
function()
>>> myAlias('item1')
>>> window.myAlias('item1')
>>> document.getElementById('item1')
<div id="item1">
웹 페이지에 넣으면 myAlias를 호출하면 다음 오류가 발생합니다.
uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: file:///[...snip...]/test.html :: <TOP_LEVEL> :: line 7" data: no]
Chrome (명확성을 위해 >>>이 삽입 됨) :
>>> window.myAlias = document.getElementById
function getElementById() { [native code] }
>>> window.myAlias('item1')
TypeError: Illegal invocation
>>> document.getElementById('item1')
<div id=?"item1">?
그리고 테스트 페이지에서 동일한 "불법 호출"을 얻습니다.
내가 뭘 잘못하고 있니? 다른 사람이 이것을 재현 할 수 있습니까?
또한 이상하게도 IE8에서 작동합니다.
해당 메서드를 문서 개체에 바인딩해야합니다. 보기:
>>> $ = 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();">
간단한 별칭을 수행 할 때 함수는 문서 개체가 아닌 전역 개체에서 호출됩니다. 이 문제를 해결하려면 클로저라는 기술을 사용하십시오.
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();">
이렇게하면 원본 개체에 대한 참조가 손실되지 않습니다.
2012 년에는 bind
더 멋진 방식으로이를 수행 할 수있는 ES5 의 새로운 방법이 있습니다.
>>> $ = document.getElementById.bind(document)
>>> $('bn_home')
<body id="bn_home" onload="init();">
이 특정 행동을 이해하기 위해 깊이 파고 들었고 좋은 설명을 찾은 것 같습니다.
별칭을 사용할 수없는 이유를 알아보기 전에 document.getElementById
JavaScript 함수 / 객체의 작동 방식을 설명하겠습니다.
JavaScript 함수를 호출 할 때마다 JavaScript 인터프리터는 범위를 결정하고이를 함수에 전달합니다.
다음 기능을 고려하십시오.
function sum(a, b)
{
return a + b;
}
sum(10, 20); // returns 30;
이 함수는 Window 범위에서 선언되며 호출 할 때 this
sum 함수 내부의 값이 전역 Window
개체가됩니다.
'sum'함수의 경우 'this'가 사용하지 않기 때문에 값이 무엇인지는 중요하지 않습니다.
다음 기능을 고려하십시오.
function Person(birthDate)
{
this.birthDate = birthDate;
this.getAge = function() { return new Date().getFullYear() - this.birthDate.getFullYear(); };
}
var dave = new Person(new Date(1909, 1, 1));
dave.getAge(); //returns 100.
당신이 dave.getAge 함수를 호출 할 때, 자바 스크립트 인터프리터는 당신이에 getAge 함수를 호출하는 것을보고 dave
는 설정 때문에, 객체 this
로 dave
하고, 호출 getAge
기능. getAge()
올바르게 반환 100
됩니다.
JavaScript에서 apply
메서드를 사용하여 범위를 지정할 수 있음을 알 수 있습니다 . 시도해 봅시다.
var dave = new Person(new Date(1909, 1, 1)); //Age 100 in 2009
var bob = new Person(new Date(1809, 1, 1)); //Age 200 in 2009
dave.getAge.apply(bob); //returns 200.
위 줄에서 JavaScript가 범위를 결정하도록하는 대신 범위를 bob
개체 로 수동으로 전달 합니다. getAge
이제 개체 에 대해 200
'생각'했음에도 불구하고 반환됩니다 .getAge
dave
위의 모든 것의 요점은 무엇입니까? 함수는 JavaScript 객체에 '느슨하게'연결됩니다. 예를 들어 할 수 있습니다.
var dave = new Person(new Date(1909, 1, 1));
var bob = new Person(new Date(1809, 1, 1));
bob.getAge = function() { return -1; };
bob.getAge(); //returns -1
dave.getAge(); //returns 100
다음 단계로 넘어 갑시다.
var dave = new Person(new Date(1909, 1, 1));
var ageMethod = dave.getAge;
dave.getAge(); //returns 100;
ageMethod(); //returns ?????
ageMethod
실행하면 오류가 발생합니다! 어떻게 된 거예요?
주의 깊게 내 위의 포인트를 읽는다면, 당신은주의 할 dave.getAge
메소드가 호출되었습니다 dave
로 this
자바 스크립트의 '범위'판별 할 수 없습니다 반면 개체를 ageMethod
실행합니다. 그래서 글로벌 '창'을 'this'로 전달했습니다. 이제 속성 window
이 없으므로 실행이 실패합니다.birthDate
ageMethod
이 문제를 해결하는 방법? 단순한,
ageMethod.apply(dave); //returns 100.
위의 모든 내용이 이해 되었습니까? 그렇다면 별칭을 사용할 수없는 이유를 설명 할 수 있습니다 document.getElementById
.
var $ = document.getElementById;
$('someElement');
$
로 호출 window
로 this
하고있는 경우 getElementById
구현이 기대 this
될 document
, 그것은 실패합니다.
다시이 문제를 해결하려면
$.apply(document, ['someElement']);
그렇다면 Internet Explorer에서 작동하는 이유는 무엇입니까?
I don't know the internal implementation of getElementById
in IE, but a comment in jQuery source (inArray
method implementation) says that in IE, window == document
. If that's the case, then aliasing document.getElementById
should work in IE.
To illustrate this further, I have created an elaborate example. Have a look at the Person
function below.
function Person(birthDate)
{
var self = this;
this.birthDate = birthDate;
this.getAge = function()
{
//Let's make sure that getAge method was invoked
//with an object which was constructed from our Person function.
if(this.constructor == Person)
return new Date().getFullYear() - this.birthDate.getFullYear();
else
return -1;
};
//Smarter version of getAge function, it will always refer to the object
//it was created with.
this.getAgeSmarter = function()
{
return self.getAge();
};
//Smartest version of getAge function.
//It will try to use the most appropriate scope.
this.getAgeSmartest = function()
{
var scope = this.constructor == Person ? this : self;
return scope.getAge();
};
}
For the Person
function above, here's how the various getAge
methods will behave.
Let's create two objects using Person
function.
var yogi = new Person(new Date(1909, 1,1)); //Age is 100
var anotherYogi = new Person(new Date(1809, 1, 1)); //Age is 200
console.log(yogi.getAge()); //Output: 100.
Straight forward, getAge method gets yogi
object as this
and outputs 100
.
var ageAlias = yogi.getAge;
console.log(ageAlias()); //Output: -1
JavaScript interepreter sets window
object as this
and our getAge
method will return -1
.
console.log(ageAlias.apply(yogi)); //Output: 100
If we set the correct scope, you can use ageAlias
method.
console.log(ageAlias.apply(anotherYogi)); //Output: 200
If we pass in some other person object, it will still calculate age correctly.
var ageSmarterAlias = yogi.getAgeSmarter;
console.log(ageSmarterAlias()); //Output: 100
The ageSmarter
function captured the original this
object so now you don't have to worry about supplying correct scope.
console.log(ageSmarterAlias.apply(anotherYogi)); //Output: 100 !!!
The problem with ageSmarter
is that you can never set the scope to some other object.
var ageSmartestAlias = yogi.getAgeSmartest;
console.log(ageSmartestAlias()); //Output: 100
console.log(ageSmartestAlias.apply(document)); //Output: 100
The ageSmartest
function will use the original scope if an invalid scope is supplied.
console.log(ageSmartestAlias.apply(anotherYogi)); //Output: 200
You will still be able to pass another Person
object to getAgeSmartest
. :)
This is a short answer.
The following makes a copy of (a reference to) the function. The problem is that now the function is on the window
object when it was designed to live on the document
object.
window.myAlias = document.getElementById
The alternatives are
- to use a wrapper (already mentioned by Fabien Ménager)
or you can use two aliases.
window.d = document // A renamed reference to the object window.d.myAlias = window.d.getElementById
Another short answer, just for wrapping/aliasing console.log
and similar logging methods. They all expect to be in the console
context.
This is usable when wrapping console.log
with some fallbacks, in case you or your users have run into trouble when using a browser that doesn't (always) support it. This is not a full solution to that problem though, as it needs to be expanded checks and a fallback - your mileage may vary.
Example using warnings
var warn = function(){ console.warn.apply(console, arguments); }
Then use it as usual
warn("I need to debug a number and an object", 9999, { "user" : "Joel" });
If you prefer to see your logging arguments wrapped in an array (I do, most of the time), substitute .apply(...)
with .call(...)
.
Should work with console.log()
, console.debug()
, console.info()
, console.warn()
, console.error()
. See also console
on MDN.
In addition to other great answers, there's simple jQuery method $.proxy.
You can alias like this:
myAlias = $.proxy(document, 'getElementById');
Or
myAlias = $.proxy(document.getElementById, document);
You actually can't "pure alias" a function on a predefined object. Therefore, the closest to aliasing you can get without wrapping is by staying within the same object:
>>> document.s = document.getElementById;
>>> document.s('myid');
<div id="myid">
참고URL : https://stackoverflow.com/questions/1007340/javascript-function-aliasing-doesnt-seem-to-work
'programing' 카테고리의 다른 글
스위프트 언어 NSClassFromString (0) | 2020.10.04 |
---|---|
하나의 Sublime Text 3 창에 둘 이상의 폴더 / 프로젝트 (0) | 2020.10.04 |
SurfaceView를 투명하게 만드는 방법 (0) | 2020.10.04 |
하이퍼 링크 클릭시 자바 스크립트 함수 호출 (0) | 2020.10.04 |
레이블을 클릭하여 HTML 라디오 버튼을 전환합니다. (0) | 2020.10.04 |