모든 프로그래머가 알아야 할 JavaScript의 "숨겨진 기능"은 무엇입니까?
다음 질문에 대한 답변의 우수한 품질을 본 후 JavaScript를 요청할 때가되었다고 생각했습니다.
자바 스크립트가 현재 가장 중요한 클라이언트 측 언어 임에도 불구하고 (Google에 물어보기 만해도) 대부분의 웹 개발자가 얼마나 강력한 지 알고있는 것은 놀라운 일입니다.
모든 프로그래머가 알아야 할 JavaScript의 "숨겨진 기능"은 무엇입니까?
다음 질문에 대한 답변의 우수한 품질을 본 후 JavaScript를 요청할 때가되었다고 생각했습니다.
자바 스크립트가 현재 가장 중요한 클라이언트 측 언어 임에도 불구하고 (Google에 물어보기 만해도) 대부분의 웹 개발자가 얼마나 강력한 지 알고있는 것은 놀라운 일입니다.
답변:
함수에 매개 변수를 정의 할 필요는 없습니다. 함수의 arguments
배열과 같은 객체를 사용할 수 있습니다 .
function sum() {
var retval = 0;
for (var i = 0, len = arguments.length; i < len; ++i) {
retval += arguments[i];
}
return retval;
}
sum(1, 2, 3) // returns 6
arguments
객체를 참조하는 것만 으로 함수 호출이 훨씬 느려집니다. if (false) 인수; 성능을 손상시킬 수 있습니다.
arguments.callee
더 이상 사용되지 않습니다.
Douglas Crockford의 훌륭한 책 JavaScript : The Good Parts 의 대부분을 인용 할 수 있습니다 . 있습니다.
하지만, 당신을 위해 하나 할게요 항상 사용 ===
하고 !==
대신 ==
하고!=
alert('' == '0'); //false
alert(0 == ''); // true
alert(0 =='0'); // true
==
전이되지 않습니다. 사용 ===
하면 예상대로 이러한 모든 진술에 대해 거짓을 줄 것입니다.
==
입니다 '\n\t\r ' == 0
=> true
D : ...
함수는 JavaScript에서 일류 시민입니다.
var passFunAndApply = function (fn,x,y,z) { return fn(x,y,z); };
var sum = function(x,y,z) {
return x+y+z;
};
alert( passFunAndApply(sum,3,4,5) ); // 12
함수형 프로그래밍 기술을 사용하여 우아한 자바 스크립트 작성 .
특히 함수는 매개 변수로 전달 될 수 있습니다. 예를 들어 Array.filter () 는 콜백을 허용합니다.
[1, 2, -1].filter(function(element, index, array) { return element > 0 });
// -> [1,2]
특정 함수의 범위 내에서만 존재하는 "비공개"함수를 선언 할 수도 있습니다.
function PrintName() {
var privateFunction = function() { return "Steve"; };
return privateFunction();
}
new Function()
만큼 악하다 eval
. 사용하지 마세요.
in 연산자를 사용하여 객체에 키가 있는지 확인할 수 있습니다 .
var x = 1;
var y = 3;
var list = {0:0, 1:0, 2:0};
x in list; //true
y in list; //false
1 in list; //true
y in {3:0, 4:0, 5:0}; //true
객체 리터럴이 너무 추한 경우이를 매개 변수가없는 함수 팁과 결합 할 수 있습니다.
function list()
{ var x = {};
for(var i=0; i < arguments.length; ++i) x[arguments[i]] = 0;
return x
}
5 in list(1,2,3,4,5) //true
변수에 기본값 지정
||
대입 식에서 논리 또는 연산자 를 사용하여 기본값을 제공 할 수 있습니다 .
var a = b || c;
a
변수의 값을 얻을 것이다 c
경우 만 b
입니다 falsy (경우 null
, false
, undefined
, 0
, empty string
, 또는 NaN
), 그렇지 않은 경우 a
의 값을 얻을 것이다b
.
이것은 제공되지 않는 경우 인수에 기본값을 지정하려는 경우 함수에서 유용합니다.
function example(arg1) {
arg1 || (arg1 = 'default value');
}
이벤트 핸들러의 IE 대체 예 :
function onClick(e) {
e || (e = window.event);
}
다음과 같은 언어 기능이 오랫동안 우리와 함께 있었으며 모든 JavaScript 구현이이를 지원하지만 ECMAScript 5th Edition 까지는 사양의 일부가 아닙니다 .
debugger
문
설명 : § 12.15 디버거 문
이 문장을 사용하면 다음 과 같이 코드에 프로그래밍 방식 으로 중단 점 을 넣을 수 있습니다 .
// ...
debugger;
// ...
디버거가 있거나 활성 상태이면 해당 줄에서 바로 중단됩니다.
그렇지 않으면 디버거가 없거나 활성화되어 있으면이 명령문은 관찰 가능한 효과가 없습니다.
여러 줄 문자열 리터럴
설명 : § 7.8.4 문자열 리터럴
var str = "This is a \
really, really \
long line!";
당신은 조심해야 캐릭터 때문에 옆에 \
있어야 당신은 뒤에 공백이있는 경우, 라인 종결 될 \
예를 들어, 코드는 것 보면 정확히 같은,하지만이 인상됩니다 SyntaxError
.
JavaScript에는 블록 범위가 없습니다 (하지만 클로저가 있으므로 호출해도됩니까?).
var x = 1;
{
var x = 2;
}
alert(x); // outputs 2
[]
대신에 객체 속성에 액세스 할 수 있습니다.
이를 통해 변수와 일치하는 속성을 찾을 수 있습니다.
obj = {a:"test"};
var propname = "a";
var b = obj[propname]; // "test"
이 이름을 사용하여 이름이 유효한 식별자가 아닌 객체 속성을 가져 오거나 설정할 수 있습니다.
obj["class"] = "test"; // class is a reserved word; obj.class would be illegal.
obj["two words"] = "test2"; // using dot operator not possible with the space.
어떤 사람들은 이것을 알고 사용하게하지 평가 () A는이 같은, 정말 나쁜 생각을 :
var propname = "a";
var a = eval("obj." + propname);
이것은 읽기가 어렵고 (jslint를 사용할 수 없음) 오류를 찾기가 어렵고 실행 속도가 느리고 XSS 악용으로 이어질 수 있습니다.
foo.bar
어쨌든 사양에 따르면 다음과 같이 동작 foo["bar"]
합니다. 또한 모든 것이 문자열 속성이라는 점에 유의하십시오. 배열 액세스를 수행하더라도 array[4]
, 4는 문자열로 변환됩니다 (적어도 ECMAScript v3 사양에 따름)
특정 주제에 대해 알맞은 JavaScript 참조를 검색하려면 검색어에 "mdc"키워드를 포함 시키십시오. 첫 번째 결과는 Mozilla 개발자 센터에서 얻은 것입니다. 오프라인 참조 나 책을 가지고 다니지 않습니다. 나는 항상 "mdc"키워드 트릭을 사용하여 내가 원하는 것을 직접 얻습니다. 예를 들면 다음과 같습니다.
Google : 자바 스크립트 배열 정렬 mdc
(대부분의 경우 '자바 스크립트'를 생략 할 수 있음)
업데이트 : Mozilla Developer Center의 이름이 Mozilla Developer Network 로 변경되었습니다 . "mdc"키워드 트릭은 여전히 작동하지만 머지 않아 "mdn"사용 을 시작 해야 할 수도 있습니다 .
어쩌면 어떤 사람들에게는 조금 분명 할 것입니다 ...
Firebug를 설치 하고 console.log ( "hello")를 사용하십시오. 임의의 alert ();을 사용하는 것보다 훨씬 낫습니다. 몇 년 전 많은 일을 기억합니다.
개인 방법
객체는 전용 메소드를 가질 수 있습니다.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
// A private method only visible from within this constructor
function calcFullName() {
return firstName + " " + lastName;
}
// A public method available to everyone
this.sayHello = function () {
alert(calcFullName());
}
}
//Usage:
var person1 = new Person("Bob", "Loblaw");
person1.sayHello();
// This fails since the method is not visible from this scope
alert(person1.calcFullName());
또한 Crockford의 "자바 스크립트 : 좋은 부분"에 언급되어 있습니다.
parseInt()
위험합니다. 적절한 밑줄을 알리지 않고 문자열을 전달하면 예기치 않은 숫자가 반환 될 수 있습니다. 예를 들어 parseInt('010')
10이 아닌 8을 반환합니다. 기본을 parseInt에 전달하면 제대로 작동합니다.
parseInt('010') // returns 8! (in FF3)
parseInt('010', 10); // returns 10 because we've informed it which base to work with.
Math.floor
나 Number
? 10 === Math.floor("010"); 10 === Number("010");
수레 :42 === Math.floor("42.69"); 42.69 === Number("42.69");
parseInt
기능은 쉽게 무해 하지 않은 일을하도록 만들 수 있습니다.
__parseInt = parseInt; parseInt = function (str, base) { if (!base) throw new Error(69, "All your base belong to us"); return __parseInt(str, base); }
함수는 객체이므로 속성을 가질 수 있습니다.
fn = 함수 (x) { // ... } fn.foo = 1; fn.next = 기능 (y) { // }
자체 실행 기능을 말해야합니다.
(function() { alert("hi there");})();
Javascript 에는 블록 범위가 없으므로 로컬 변수를 정의하려는 경우 자체 실행 기능을 사용할 수 있습니다.
(function() {
var myvar = 2;
alert(myvar);
})();
여기서는 myvar
전역 범위를 방해하거나 오염시키지 않으며 함수가 종료되면 사라집니다.
.js
파일을 익명의 자체 실행 기능으로 묶고 전역 적으로 액세스 할 수있는 모든 것을 window
객체에 첨부 합니다. 글로벌 네임 스페이스 오염을 방지합니다.
함수가 예상하는 매개 변수 수를 알 수 있습니다
function add_nums(num1, num2, num3 ){
return num1 + num2 + num3;
}
add_nums.length // 3 is the number of parameters expected.
함수가 얼마나 많은 매개 변수를 수신하는지 파악
function add_many_nums(){
return arguments.length;
}
add_many_nums(2,1,122,12,21,89); //returns 6
function.length
.
다음은 흥미로운 것들입니다.
NaN
(심지어 아무것도하는 NaN
) 포함하는, 항상 false입니다 ==
, <
하고 >
.NaN
숫자가 아님을 나타내지 만 유형을 요청하면 실제로 숫자를 반환합니다.Array.sort
비교기 함수를 사용할 수 있으며 퀵 정렬과 같은 드라이버에 의해 호출됩니다 (구현에 따라 다름).$0
, $1
, $2
정규식에 대한 회원.null
다른 것과는 다릅니다. 객체, 부울, 숫자, 문자열 또는도 아닙니다 undefined
. "alternate"와 비슷합니다 undefined
. (참고 : typeof null == "object"
)this
이 지정되지 않은 [Global] 객체를 생성합니다.var
자동 선언에 의존하지 선언하면 런타임에서 해당 변수에 대한 액세스를 최적화 할 수 있습니다with
구조는 optimzations을 파괴 할 것이다break
. 루프의 레이블을 지정하고 대상으로 사용할 수 있습니다 continue
.undefined
. (구현에 따라 다름)if (new Boolean(false)) {...}
{...}
블록 을 실행합니다[좋은 의견에 대한 답변으로 조금 업데이트되었습니다. 의견을 참조하십시오]
typeof null
"객체"를 반환합니다.
undefined
. 그러나 존재하지 않는 인덱스를 찾을 때 얻는 기본값입니다. a [2000]을 체크 undefined
했다하더라도 이것이 메모리이지만 아직 메모리를 할당 한 것은 아닙니다. IE8에서는 당시 JScript 엔진의 느낌에 따라 일부 배열이 밀도가 높고 일부 배열이 희박합니다. 자세한 내용은 여기 읽기 : blogs.msdn.com/jscript/archive/2008/04/08/...
나는 파티에 늦었다는 것을 알고 있지만, +
"숫자를 숫자로 변환"을 넘어서서 운영자의 유용성이 언급되지 않았다는 것을 믿을 수 없다 . 어쩌면 그것은 기능이 얼마나 숨겨져 있습니까?
// Quick hex to dec conversion:
+"0xFF"; // -> 255
// Get a timestamp for now, the equivalent of `new Date().getTime()`:
+new Date();
// Safer parsing than parseFloat()/parseInt()
parseInt("1,000"); // -> 1, not 1000
+"1,000"; // -> NaN, much better for testing user input
parseInt("010"); // -> 8, because of the octal literal prefix
+"010"; // -> 10, `Number()` doesn't parse octal literals
// A use case for this would be rare, but still useful in cases
// for shortening something like if (someVar === null) someVar = 0;
+null; // -> 0;
// Boolean to integer
+true; // -> 1;
+false; // -> 0;
// Other useful tidbits:
+"1e10"; // -> 10000000000
+"1e-4"; // -> 0.0001
+"-12"; // -> -12
물론, 당신은 Number()
대신 에이 모든 것을 할 수 있지만, +
운영자는 훨씬 더 예쁘다!
프로토 타입의 valueOf()
메서드를 재정 의하여 개체의 숫자 반환 값을 정의 할 수도 있습니다 . 해당 객체에서 수행 된 숫자 변환은을 발생시키지 NaN
않지만 valueOf()
메소드 의 반환 값은 다음과 같습니다.
var rnd = {
"valueOf": function () { return Math.floor(Math.random()*1000); }
};
+rnd; // -> 442;
+rnd; // -> 727;
+rnd; // -> 718;
0xFF
, 등의 필요를 +"0xFF"
.
0xFF
쓸 수있는 것과 거의 같은 방식으로 글을 쓸 수 있습니다 . 나는 당신이 사용할 수있는 제안1
+true
+("0x"+somevar)
parseInt(somevar, 16)
원하는 경우 의 대안으로 .
" 자바 스크립트의 확장 방법 프로토 타입 속성을 통해".
Array.prototype.contains = function(value) {
for (var i = 0; i < this.length; i++) {
if (this[i] == value) return true;
}
return false;
}
contains
모든 Array
객체에 메소드 가 추가 됩니다. 이 구문을 사용하여이 메소드를 호출 할 수 있습니다
var stringArray = ["foo", "bar", "foobar"];
stringArray.contains("foobar");
객체에서 속성을 올바르게 제거하려면 속성을 undefined로 설정하는 대신 속성을 삭제해야합니다 .
var obj = { prop1: 42, prop2: 43 };
obj.prop2 = undefined;
for (var key in obj) {
...
prop2 특성 은 여전히 반복의 일부입니다. 완전히 없애고 싶다면prop2 하려면 대신 다음을 수행해야합니다.
delete obj.prop2;
속성을 반복 할 때 prop2 속성 이 더 이상 나타나지 않습니다.
with
.
거의 사용되지 않고 솔직하게도 거의 사용되지 않습니다 ... 그러나 제한된 상황에서는 용도가 있습니다.
예를 들어, 객체 리터럴은 새 객체 에서 속성을 빠르게 설정하는 데 매우 편리 합니다. 그러나 기존 객체의 속성 중 절반 을 변경해야하는 경우 어떻게해야 합니까?
var user =
{
fname: 'Rocket',
mname: 'Aloysus',
lname: 'Squirrel',
city: 'Fresno',
state: 'California'
};
// ...
with (user)
{
mname = 'J';
city = 'Frostbite Falls';
state = 'Minnesota';
}
Alan Storm은 이것이 다소 위험 할 수 있다고 지적합니다. 컨텍스트로 사용 된 개체 에 할당 된 속성 중 하나 가없는 경우 외부 범위에서 해결되어 전역 변수를 만들거나 덮어 쓸 수 있습니다. 기본 또는 빈 값을 가진 속성이 정의되지 않은 객체에서 작업하기 위해 코드를 작성하는 데 사용하는 경우 특히 위험합니다.
var user =
{
fname: "John",
// mname definition skipped - no middle name
lname: "Doe"
};
with (user)
{
mname = "Q"; // creates / modifies global variable "mname"
}
따라서 with
그러한 과제 에 대한 진술 의 사용을 피하는 것이 좋습니다 .
작업하도록 설계된 유형이 아닌 객체에서 메서드 (또는 함수)를 호출 할 수 있습니다. 이것은 사용자 정의 객체에서 기본 (빠른) 메소드를 호출하는 데 좋습니다.
var listNodes = document.getElementsByTagName('a');
listNodes.sort(function(a, b){ ... });
이 코드 listNodes
는Array
Array.prototype.sort.apply(listNodes, [function(a, b){ ... }]);
이 코드 listNodes
는에서 사용할 배열과 같은 속성 (길이, [] 연산자)을 충분히 정의하기 때문에 작동 합니다 sort()
.
프로토 타이 상속 (Douglas Crockford에 의해 대중화 됨)은 Javascript의 많은 것들에 대해 생각하는 방식을 완전히 혁신시킵니다.
Object.beget = (function(Function){
return function(Object){
Function.prototype = Object;
return new Function;
}
})(function(){});
살인자 야! 거의 아무도 그것을 사용하지 않는 것이 유감입니다.
다른 객체에 대한 (실제) 프로토 타입 상속 링크를 유지하면서 객체의 새 인스턴스를 "얻고"확장 할 수 있습니다. 예:
var A = {
foo : 'greetings'
};
var B = Object.beget(A);
alert(B.foo); // 'greetings'
// changes and additionns to A are reflected in B
A.foo = 'hello';
alert(B.foo); // 'hello'
A.bar = 'world';
alert(B.bar); // 'world'
// ...but not the other way around
B.foo = 'wazzap';
alert(A.foo); // 'hello'
B.bar = 'universe';
alert(A.bar); // 'world'
어떤 사람들은 이것을 맛의 문제라고 부르지 만,
aWizz = wizz || "default";
// same as: if (wizz) { aWizz = wizz; } else { aWizz = "default"; }
삼항 연산자는 구성표처럼 작동하도록 연결될 수 있습니다 (조건 ...).
(cond (predicate (action ...))
(predicate2 (action2 ...))
(#t default ))
로 쓸 수 있습니다 ...
predicate ? action( ... ) :
predicate2 ? action2( ... ) :
default;
부작용없이 코드를 분기하므로 매우 "기능적"입니다. 따라서 대신 :
if (predicate) {
foo = "one";
} else if (predicate2) {
foo = "two";
} else {
foo = "default";
}
당신은 쓸 수 있습니다:
foo = predicate ? "one" :
predicate2 ? "two" :
"default";
재귀와도 잘 작동합니다 :)
숫자도 객체입니다. 따라서 다음과 같은 멋진 작업을 수행 할 수 있습니다.
// convert to base 2
(5).toString(2) // returns "101"
// provide built in iteration
Number.prototype.times = function(funct){
if(typeof funct === 'function') {
for(var i = 0;i < Math.floor(this);i++) {
funct(i);
}
}
return this;
}
(5).times(function(i){
string += i+" ";
});
// string now equals "0 1 2 3 4 "
var x = 1000;
x.times(function(i){
document.body.innerHTML += '<p>paragraph #'+i+'</p>';
});
// adds 1000 parapraphs to the document
times
비효율적입니다. Math.floor
매번 한 번이 아니라 매번 호출됩니다.
JavaScript에서 클로저 (C # v2.0 +의 익명 메소드와 유사)는 어떻습니까 ? 함수 또는 "표현식"을 작성하는 함수를 작성할 수 있습니다.
폐쇄 예 :
//Takes a function that filters numbers and calls the function on
//it to build up a list of numbers that satisfy the function.
function filter(filterFunction, numbers)
{
var filteredNumbers = [];
for (var index = 0; index < numbers.length; index++)
{
if (filterFunction(numbers[index]) == true)
{
filteredNumbers.push(numbers[index]);
}
}
return filteredNumbers;
}
//Creates a function (closure) that will remember the value "lowerBound"
//that gets passed in and keep a copy of it.
function buildGreaterThanFunction(lowerBound)
{
return function (numberToCheck) {
return (numberToCheck > lowerBound) ? true : false;
};
}
var numbers = [1, 15, 20, 4, 11, 9, 77, 102, 6];
var greaterThan7 = buildGreaterThanFunction(7);
var greaterThan15 = buildGreaterThanFunction(15);
numbers = filter(greaterThan7, numbers);
alert('Greater Than 7: ' + numbers);
numbers = filter(greaterThan15, numbers);
alert('Greater Than 15: ' + numbers);
암시 된 프로토 타입 체인 spoon16을 사용하여 클래스를 확장 (상속)하고 속성 / 방법 을 재정의 할 수도 있습니다 .
다음 예제에서는 Pet 클래스를 만들고 몇 가지 속성을 정의합니다. 또한 Object에서 상속 된 .toString () 메서드를 재정의합니다.
그런 다음 Pet 를 확장하고 .toString () 메서드를 재정 의하여 동작 (다형성)을 다시 변경 하는 Dog 클래스를 만듭니다 . 또한 자식 클래스에 다른 속성을 추가합니다.
그런 다음 상속 체인을 검사하여 Dog가 여전히 Dog 유형, Pet 유형 및 Object 유형임을 보여줍니다.
// Defines a Pet class constructor
function Pet(name)
{
this.getName = function() { return name; };
this.setName = function(newName) { name = newName; };
}
// Adds the Pet.toString() function for all Pet objects
Pet.prototype.toString = function()
{
return 'This pets name is: ' + this.getName();
};
// end of class Pet
// Define Dog class constructor (Dog : Pet)
function Dog(name, breed)
{
// think Dog : base(name)
Pet.call(this, name);
this.getBreed = function() { return breed; };
}
// this makes Dog.prototype inherit from Pet.prototype
Dog.prototype = new Pet();
// Currently Pet.prototype.constructor
// points to Pet. We want our Dog instances'
// constructor to point to Dog.
Dog.prototype.constructor = Dog;
// Now we override Pet.prototype.toString
Dog.prototype.toString = function()
{
return 'This dogs name is: ' + this.getName() +
', and its breed is: ' + this.getBreed();
};
// end of class Dog
var parrotty = new Pet('Parrotty the Parrot');
var dog = new Dog('Buddy', 'Great Dane');
// test the new toString()
alert(parrotty);
alert(dog);
// Testing instanceof (similar to the `is` operator)
alert('Is dog instance of Dog? ' + (dog instanceof Dog)); //true
alert('Is dog instance of Pet? ' + (dog instanceof Pet)); //true
alert('Is dog instance of Object? ' + (dog instanceof Object)); //true
이 질문에 대한 답 은 Ray Djajadinata 의 훌륭한 MSDN 기사 에서 수정 한 코드 였습니다.
유형에 따라 예외가 발생할 수 있습니다. MDC 에서 인용 :
try {
myroutine(); // may throw three exceptions
} catch (e if e instanceof TypeError) {
// statements to handle TypeError exceptions
} catch (e if e instanceof RangeError) {
// statements to handle RangeError exceptions
} catch (e if e instanceof EvalError) {
// statements to handle EvalError exceptions
} catch (e) {
// statements to handle any unspecified exceptions
logMyErrors(e); // pass exception object to error handler
}
참고 : 조건부 catch 절은 ECMAScript 사양에 포함되지 않은 Netscape (및 Mozilla / Firefox) 확장이므로 특정 브라우저를 제외하고는 신뢰할 수 없습니다.
내 머리 꼭대기에서 ...
기능
arguments.callee는 "arguments"변수를 호스팅하는 함수를 나타내므로 익명 함수를 재귀하는 데 사용할 수 있습니다.
var recurse = function() {
if (condition) arguments.callee(); //calls recurse() again
}
다음과 같이하려는 경우에 유용합니다.
//do something to all array items within an array recursively
myArray.forEach(function(item) {
if (item instanceof Array) item.forEach(arguments.callee)
else {/*...*/}
})
사물
객체 멤버에 대한 흥미로운 점 : 이름으로 문자열을 가질 수 있습니다.
//these are normal object members
var obj = {
a : function() {},
b : function() {}
}
//but we can do this too
var rules = {
".layout .widget" : function(element) {},
"a[href]" : function(element) {}
}
/*
this snippet searches the page for elements that
match the CSS selectors and applies the respective function to them:
*/
for (var item in rules) {
var elements = document.querySelectorAll(rules[item]);
for (var e, i = 0; e = elements[i++];) rules[item](e);
}
현
String.split 은 정규 표현식을 매개 변수로 사용할 수 있습니다.
"hello world with spaces".split(/\s+/g);
//returns an array: ["hello", "world", "with", "spaces"]
String.replace 는 정규 표현식을 검색 매개 변수로 사용하고 함수를 대체 매개 변수로 사용할 수 있습니다.
var i = 1;
"foo bar baz ".replace(/\s+/g, function() {return i++});
//returns "foo1bar2baz3"
arguments.callee
ECMAScript 5에서는 더 이상 사용되지 않으며 throw 및 예외가 발생합니다.
대부분의 경우 스위치 대신 객체를 사용할 수 있습니다.
function getInnerText(o){
return o === null? null : {
string: o,
array: o.map(getInnerText).join(""),
object:getInnerText(o["childNodes"])
}[typeis(o)];
}
업데이트 : 사전에 비효율적 인 평가 사례에 대해 우려하는 경우 (프로그램 설계 초기에 효율성에 대해 걱정하는 이유는 무엇입니까 ??) 다음과 같이 할 수 있습니다.
function getInnerText(o){
return o === null? null : {
string: function() { return o;},
array: function() { return o.map(getInnerText).join(""); },
object: function () { return getInnerText(o["childNodes"]; ) }
}[typeis(o)]();
}
이것은 스위치 나 객체보다 타이핑 (또는 읽기)하기가 더 쉽지만 아래 주석 섹션에 자세히 설명 된 스위치 대신 객체를 사용하는 이점을 유지합니다. 이 스타일은 또한 일단 충분히 자라면 이것을 적절한 "클래스"로 돌리는 것이 더 간단합니다.
update2 : ES.next에 대해 제안 된 구문 확장을 사용하면 다음과 같습니다.
let getInnerText = o -> ({
string: o -> o,
array: o -> o.map(getInnerText).join(""),
object: o -> getInnerText(o["childNodes"])
}[ typeis o ] || (->null) )(o);
var arr = []; typeof arr; // object
객체의 속성을 반복 할 때 hasOwnProperty 메소드 를 사용해야합니다 .
for (p in anObject) {
if (anObject.hasOwnProperty(p)) {
//Do stuff with p here
}
}
이는 anObject 의 직접 속성 에만 액세스 하고 프로토 타입 체인에있는 속성은 사용하지 않도록하기위한 것입니다.
공용 인터페이스를 가진 전용 변수
자체 호출 기능 정의와 함께 깔끔한 작은 트릭을 사용합니다. 리턴 된 오브젝트 내부의 모든 것은 공용 인터페이스에서 사용 가능하고 다른 모든 것은 개인용입니다.
var test = function () {
//private members
var x = 1;
var y = function () {
return x * 2;
};
//public interface
return {
setx : function (newx) {
x = newx;
},
gety : function () {
return y();
}
}
}();
assert(undefined == test.x);
assert(undefined == test.y);
assert(2 == test.gety());
test.setx(5);
assert(10 == test.gety());