new
사람들이 JavaScript를 객체 지향 프로그래밍 언어가 아니라고 생각하는 경향이 있기 때문에 JavaScript 의 키워드는 처음 접했을 때 상당히 혼란 스러울 수 있습니다.
- 무엇입니까?
- 어떤 문제가 해결됩니까?
- 적절한시기와시기는?
new
사람들이 JavaScript를 객체 지향 프로그래밍 언어가 아니라고 생각하는 경향이 있기 때문에 JavaScript 의 키워드는 처음 접했을 때 상당히 혼란 스러울 수 있습니다.
답변:
그것은 5 가지 일을한다 :
this
새로 만든 객체에 변수 지점을.this
언급 될 때마다 새로 작성된 객체를 사용하여 생성자 함수를 실행합니다 .null
객체 가 아닌 참조를 반환하지 않으면 새로 만든 객체를 반환합니다 . 이 경우 해당 객체 참조가 대신 반환됩니다.참고 : 생성자 함수 는 다음과 같이 new
키워드 뒤의 함수를 나타냅니다 .
new ConstructorFunction(arg1, arg2)
이 작업이 완료되면 새 객체의 정의되지 않은 속성이 요청되면 스크립트는 대신 객체의 [[prototype]] 객체에서 속성을 확인합니다. 이것은 JavaScript에서 전통적인 클래스 상속과 비슷한 것을 얻는 방법입니다.
이것에 대해 가장 어려운 부분은 포인트 번호 2입니다. 모든 객체 (함수 포함)에는 [[prototype]] 이라는 내부 속성이 있습니다. new 를 사용 하거나 Object.create 를 사용하거나 리터럴을 기준으로 오브젝트 작성시 에만 설정할 수 있습니다 (함수 기본값은 Function.prototype, 숫자는 Number.prototype 등). Object.getPrototypeOf (someObject) 로만 읽을 수 있습니다 . 이 값을 설정하거나 읽는 다른 방법 은 없습니다 .
기능, 숨겨진 외에도 [[프로토 타입]] 속성도라는 속성이 프로토 타입을 , 그리고 당신이 액세스 할 수있는이 있다는 것입니다, 수정은 당신이 할 객체에 대한 상속 된 속성 및 방법을 제공 할 수 있습니다.
예를 들면 다음과 같습니다.
ObjMaker = function() {this.a = 'first';};
// ObjMaker is just a function, there's nothing special about it that makes
// it a constructor.
ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible prototype property that
// we can alter. I just added a property called 'b' to it. Like
// all objects, ObjMaker also has an inaccessible [[prototype]] property
// that we can't do anything with
obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called obj1. At first obj1 was the same
// as {}. The [[prototype]] property of obj1 was then set to the current
// object value of the ObjMaker.prototype (if ObjMaker.prototype is later
// assigned a new object value, obj1's [[prototype]] will not change, but you
// can alter the properties of ObjMaker.prototype to add to both the
// prototype and [[prototype]]). The ObjMaker function was executed, with
// obj1 in place of this... so obj1.a was set to 'first'.
obj1.a;
// returns 'first'
obj1.b;
// obj1 doesn't have a property called 'b', so JavaScript checks
// its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
// ObjMaker.prototype has a property called 'b' with value 'second'
// returns 'second'
사용하는 모든 객체 new ObjMaker()
가 'b'속성을 상속받은 것처럼 보이기 때문에 클래스 상속과 같습니다 .
서브 클래스와 같은 것을 원한다면 다음을 수행하십시오.
SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);
SubObjMaker.prototype.c = 'third';
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype
obj2.c;
// returns 'third', from SubObjMaker.prototype
obj2.b;
// returns 'second', from ObjMaker.prototype
obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype
// was created with the ObjMaker function, which assigned a for us
마지막 으로이 페이지를 찾기 전에이 주제에 대해 많은 쓰레기를 읽었습니다. 이 페이지 는 멋진 다이어그램으로 잘 설명되어 있습니다.
ObjMaker
값을 반환하는 함수로 정의 된 경우 어떻게 달라 집니까?
new
이 존재 하므로 함수 / 객체를 구성 / 복사하기 위해 팩토리 메소드를 작성할 필요가 없습니다 . "이것을 복사하여 부모 '클래스'와 동일하게 만들고 효율적이고 정확하게 수행하며 내부적으로 JS 만 액세스 할 수있는 상속 정보를 저장합니다"라는 의미입니다. 그렇게하기 위해, 접근 불가능한 prototype
새로운 객체의 내부 를 수정하여 상속 된 멤버를 불투명하게 캡슐화하여 기존 OO 상속 체인 (런타임 수정 불가능)을 모방합니다. 없이이를 시뮬레이션 할 수 new
있지만 상속은 런타임 수정 가능합니다. 좋은? 나쁜? 당신에게 달려 있습니다.
Notice that this pattern is deprecated!
있습니다. 클래스의 프로토 타입을 설정하는 올바른 최신 패턴은 무엇입니까?
이 기능이 있다고 가정하십시오.
var Foo = function(){
this.A = 1;
this.B = 2;
};
이것을 독립형 함수로 호출하면 다음과 같습니다.
Foo();
이 함수를 실행하면 window
객체 ( A
및 B
) 에 두 가지 속성이 추가됩니다 . 받는 사람이 추가합니다 window
때문에이 window
당신이 그런 식으로 그것을 실행할 때 함수를 호출하는 객체이며, this
함수의 기능이라고하는 객체입니다. 적어도 자바 스크립트에서.
이제 다음과 같이 호출하십시오 new
.
var bar = new Foo();
new
함수 호출에 추가 하면 새 객체가 생성되고 (just var bar = new Object()
) this
함수 내에서 함수를 호출 한 객체가 아니라 방금 생성 한 새 객체가 함수 내부를 가리키는 Object
것입니다. 그래서 bar
지금의 속성을 가진 객체입니다 A
및 B
. 모든 함수는 생성자가 될 수 있으며 항상 의미가있는 것은 아닙니다.
window
암시 적 으로 방법입니다 . 비록 익명이라도 폐쇄. 그러나이 예에서는 Foo();
=> [default context].Foo();
=> 창에서 간단한 메소드 호출입니다 window.Foo();
. 이 표현 window
에는 문맥 ( 호출자 뿐만 아니라 중요하지 않음)이 있습니다.
Daniel Howard의 답변 외에도 다음과 같은 기능이 있습니다 new
.
function New(func) {
var res = {};
if (func.prototype !== null) {
res.__proto__ = func.prototype;
}
var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
return ret;
}
return res;
}
동안
var obj = New(A, 1, 2);
에 해당
var obj = new A(1, 2);
func.prototype
수 null
있습니까? 좀 더 자세히 설명해 주시겠습니까?
A.prototype = null;
.이 경우 new A()
오브젝트가 생성되고 내부 프로토 타입이 Object
오브젝트를 가리 킵니다 . jsfiddle.net/Mk42Z
Object(ret) === ret
.
typeof
테스트를 통해 배후에서 무슨 일이 일어나고 있는지 쉽게 이해할 수 있다고 생각 합니다.
브라우저 콘솔에서 다음 코드를 시도하십시오.
function Foo() {
return this;
}
var a = Foo(); //returns window object
var b = new Foo(); //returns empty object of foo
a instanceof Window; // true
a instanceof Foo; // false
b instanceof Window; // false
b instanceof Foo; // true
이제 커뮤니티 위키 답변을 읽을 수 있습니다 :)
return this;
하면 동일한 출력이 생성됩니다.
따라서 아마도 객체의 인스턴스를 생성하기위한 것이 아닙니다.
그것을 위해 정확하게 사용됩니다. 다음과 같이 함수 생성자를 정의하십시오.
function Person(name) {
this.name = name;
}
var john = new Person('John');
그러나 ECMAScript의 추가 이점은 .prototype
속성을 사용하여 확장 할 수 있으므로 다음과 같은 작업을 수행 할 수 있다는 것입니다.
Person.prototype.getName = function() { return this.name; }
이 생성자에서 생성 된 모든 객체는 이제 getName
액세스 할 수있는 프로토 타입 체인 으로 인해 생성됩니다 .
class
키워드 는 없지만 거의 같은 일을 할 수 있습니다.
JavaScript 는 객체 지향 프로그래밍 언어이며 인스턴스 작성에 정확하게 사용됩니다. 클래스 기반이 아니라 프로토 타입 기반이지만 객체 지향적이지 않다는 의미는 아닙니다.
이미 훌륭한 답변이 있지만 아래의 사례 III 에 대한 관찰을 강조하기 위해 새로운 답변을 게시하고 있습니다 new
. 아래 사례를 살펴보십시오.
사례 I :
var Foo = function(){
this.A = 1;
this.B = 2;
};
console.log(Foo()); //prints undefined
console.log(window.A); //prints 1
위의가 가리키는 익명 함수를 호출하는 일반적인 경우입니다 Foo
. 이 함수를 호출하면가 반환 undefined
됩니다. 명시적인 return 문이 없으므로 JavaScript 인터프리터 return undefined;
는 함수 끝에 명령문을 강제로 삽입 합니다. 여기서 window는 this
new A
및 B
속성 을 가져 오는 호출 객체 (contextual )입니다 .
사례 II :
var Foo = function(){
this.A = 1;
this.B = 2;
};
var bar = new Foo();
console.log(bar()); //illegal isn't pointing to a function but an object
console.log(bar.A); //prints 1
new
키워드를 보는 JavaScript 인터프리터 는에서 this
가리키는 익명 함수 의 호출 객체 (컨텍스트 ) 역할을하는 새 객체를 만듭니다 Foo
. 이 경우 A
와 B
새로 생성 된 객체가 될 속성 (window 객체 대신에). 명시적인 return 문이 없으므로 JavaScript 인터프리터는 new
키워드 사용으로 인해 생성 된 새 객체를 반환하기 위해 return 문을 강제로 삽입 합니다.
사례 III :
var Foo = function(){
this.A = 1;
this.B = 2;
return {C:20,D:30};
};
var bar = new Foo();
console.log(bar.C);//prints 20
console.log(bar.A); //prints undefined. bar is not pointing to the object which got created due to new keyword.
여기서 new
키워드를 보는 JavaScript 인터프리터 는에서 this
가리키는 익명 함수 의 호출 객체 (컨텍스트 ) 역할을하는 새 객체를 만듭니다 Foo
. 다시, A
그리고 B
새로 생성 된 객체의 속성이된다. 그러나 이번에는 명시적인 return 문이 있으므로 JavaScript 인터프리터는 자체적으로 아무것도 하지 않습니다 .
III 번의 경우주의해야 할 점은 new
키워드 로 인해 생성 된 객체가 레이더에서 손실 되었다는 것입니다 . bar
실제로 new
키워드 로 인해 JavaScript 인터프리터가 만든 것이 아닌 완전히 다른 객체를 가리키고 있습니다.
JavaScripit : David Flanagan 인용 : 결정적인 안내서 (6 판), Ch. 4, 페이지 62 :
객체 생성 표현식이 평가되면 JavaScript는 먼저 객체 이니셜 라이저 {}에 의해 생성 된 객체와 같은 빈 객체를 새로 만듭니다. 다음으로 지정된 인수를 사용하여 지정된 함수를 호출하고 this 키워드의 값으로 새 객체를 전달합니다. 그런 다음이 함수를 사용하여 새로 만든 객체의 속성을 초기화 할 수 있습니다. 생성자로 사용하기 위해 작성된 함수는 값을 반환하지 않으며 객체 생성 표현식의 값은 새로 생성되고 초기화 된 객체입니다. 생성자가 객체 값을 반환하면 해당 값은 객체 생성 표현식의 값이되고 새로 생성 된 객체는 삭제됩니다.
--- 추가 정보 ---
위의 코드 스 니펫에 사용되는 함수는 JS 세계에서 다음과 같이 특별한 이름을 갖습니다.
사례 I 및 II- 생성자 함수
사례 III- 공장 기능. 팩토리 함수 는new
현재 스레드에서 개념을 설명하기 위해 수행 한 키워드 와 함께 사용 해서는 안됩니다 .
이 스레드 에서 차이점에 대해 읽을 수 있습니다 .
때로는 코드가 단어보다 쉽습니다.
var func1 = function (x) { this.x = x; } // used with 'new' only
var func2 = function (x) { var z={}; z.x = x; return z; } // used both ways
func1.prototype.y = 11;
func2.prototype.y = 12;
A1 = new func1(1); // has A1.x AND A1.y
A2 = func1(1); // undefined ('this' refers to 'window')
B1 = new func2(2); // has B1.x ONLY
B2 = func2(2); // has B2.x ONLY
필자는 프로토 타입을 사용하지 않는 한 func2 스타일을 사용하여 함수 내부 및 외부에서 약간의 유연성을 제공합니다.
B1 = new func2(2);
<-왜 이것이 B1.y
없을까요?
new
키워드는 함수가 실행되고있는 아래의 상황을 변경하고 해당 컨텍스트에 대한 포인터를 반환한다.
new
키워드를 사용하지 않으면 함수 Vehicle()
가 실행되는 컨텍스트는 Vehicle
함수를 호출하는 컨텍스트와 동일 합니다. this
키워드는 같은 컨텍스트를 참조한다. 을 사용 new Vehicle()
하면 새 컨텍스트가 작성되므로 this
함수 내의 키워드 가 새 컨텍스트를 참조합니다. 당신이 얻는 것은 새로 작성된 컨텍스트입니다.
new
키워드는 생성자 함수에서 객체를 생성하는 자바 스크립트에 사용됩니다. new
키워드는 생성자 함수를 호출하기 전에 배치하는 다음과 같은 일을 할 것입니다 :
this
키워드를 새로 만든 객체에 바인딩하고 생성자 함수를 실행합니다function Dog (age) {
this.age = age;
}
const doggie = new Dog(12);
console.log(doggie);
console.log(doggie.__proto__ === Dog.prototype) // true
정확히 무슨 일이 :
const doggie
말한다 : 우리는 변수를 선언하기 위해 메모리가 필요합니다.=
는 다음과 같이 말합니다.=
new Dog(12)
입니다. JS 엔진은 새 키워드를보고 새 개체를 만들고 프로토 타입을 Dog.prototype으로 설정합니다.this
새 객체로 설정된 값으로 실행됩니다 . 이 단계에서는 새로 만든 강아지 개체에 연령이 할당됩니다.new
키워드는 생성자 등의 기능을 사용하여 개체의 인스턴스를 생성합니다. 예를 들어 :
var Foo = function() {};
Foo.prototype.bar = 'bar';
var foo = new Foo();
foo instanceof Foo; // true
인스턴스 prototype
는 생성자 함수 에서 상속됩니다 . 위의 예를 들어 ...
foo.bar; // 'bar'
JavaScript는 항상 원본 사양 EcmaScript의 구현이므로 플랫폼마다 크게 다를 수 있습니다.
어쨌든 EcmaScript 사양을 따르는 모든 JavaScript 구현은 구현과는 별도로 Object Oriented Language를 제공합니다. ES 표준에 따르면 :
ECMAScript는 호스트 환경 내에서 계산을 수행하고 계산 객체를 조작하기위한 객체 지향 프로그래밍 언어입니다.
이제 JavaScript가 EcmaScript의 구현이므로 객체 지향 언어라는 데 동의했습니다. new
모든 객체 지향 언어로 작업을 정의 하면 이러한 키워드는 특정 유형의 클래스 (C #과 같은 경우 익명 유형 포함)에서 객체 인스턴스를 만드는 데 사용됩니다.
EcmaScript에서는 스펙에서 읽을 수있는 클래스를 사용하지 않습니다.
ECMAScript는 C ++, Smalltalk 또는 Java와 같은 클래스를 사용하지 않습니다. 대신 객체는 리터럴 표기법 또는 객체를 생성 한 다음 생성자를 통해 속성을 초기화하여 코드의 전체 또는 일부를 초기화하는 생성자를 통해 다양한 방법으로 생성 될 수 있습니다. 각 생성자는 프로토 타입 기반 상속 및 공유 속성을 구현하는 데 사용되는“prototype”이라는 속성을 가진 함수입니다. 객체는
새로운 표현식에서 생성자를 사용하여 생성됩니다 . 예를 들어 new Date (2009,11)는 새 Date 객체를 만듭니다. new를 사용하지 않고 생성자를 호출하면 생성자에 따라 결과가 달라집니다. 예를 들어, Date ()는 객체가 아닌 현재 날짜와 시간의 문자열 표현을 생성합니다.