프로토타입은 JavaScript의 노트 중 이해하기 어려운 부분입니다. 여기서는 JS의 프로토타입에 대해 몇 가지 핵심 지식을 통해 설명하겠습니다. 구체적인 내용은 아래 세부정보를 참조하세요.
프로토타입 디자인 패턴 1개
clone()을 사용하여 .Net에서 프로토타입 메서드를 구현할 수 있습니다
프로토타입 방식의 주요 아이디어는 이제 클래스 A가 있는데, 클래스 B를 만들고 싶다는 것입니다. 이 클래스는 A를 기반으로 하며 확장이 가능합니다. 우리는 B의 원형을 A라고 부릅니다.
2개의 JavaScript 메서드는 세 가지 범주로 나눌 수 있습니다.
수업 방법
b 객체 메소드
c 프로토타입 방법
예:
function People(name) { this.name=name; //对象方法 this.Introduce=function(){ alert("My name is "+this.name); } } //类方法 People.Run=function(){ alert("I can run"); } //原型方法 People.prototype.IntroduceChinese=function(){ alert("我的名字是"+this.name); } //测试 var p1=new People("Windking"); p1.Introduce(); People.Run(); p1.IntroduceChinese();
3 obj1.func.call(obj) 메서드
obj를 obj1로 취급하고 func 메서드를 호출한다는 뜻입니다
자, 문제를 하나씩 해결해 보겠습니다.
프로토타입이 무슨 뜻인가요?
Javascript의 모든 객체에는 프로토타입 속성이 있습니다. Javascript에서 객체의 프로토타입 속성에 대한 설명은 객체 유형의 프로토타입에 대한 참조를 반환한다는 것입니다.
A.prototype = new B();
프로토타입을 이해하는 것을 상속과 혼동해서는 안 됩니다. A의 프로토타입은 B의 인스턴스입니다. A가 B의 모든 메서드와 속성을 복제한 것으로 이해할 수 있습니다. A는 B의 메서드와 속성을 사용할 수 있습니다. 여기서 강조점은 상속보다는 복제에 있습니다. 이런 상황이 발생할 수 있습니다. A의 프로토타입은 B의 인스턴스이고 B의 프로토타입도 A의 인스턴스입니다.
실험적인 예를 살펴보겠습니다.
function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } } function extendClass() { } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg(); // 显示baseClass::showMsg
먼저 baseClass 클래스를 정의한 다음, ExtentClass를 정의하는데, 프로토타입으로 baseClass의 인스턴스를 사용할 계획이고, 복제할 ExtendedClass에도 showMsg 객체 메소드가 포함되어 있습니다.
extendClass.prototype = new baseClass()는 다음과 같이 읽을 수 있습니다. ExtensionClass는 baseClass의 인스턴스를 프로토타입으로 복제하여 생성됩니다.
그렇다면 'extendClass 자체에 baseClass의 메소드와 동일한 이름의 메소드가 포함되어 있으면 어떻게 될까요?'라는 질문이 생길 것입니다.
다음은 확장 실험 2입니다.
function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } } function extendClass() { this.showMsg =function () { alert("extendClass::showMsg"); } } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg();//显示extendClass::showMsg
실험적 증명: 함수가 실행되면 먼저 온톨로지에서 함수를 찾고, 찾을 수 없으면 프로토타입에서 함수를 찾습니다. 또는 프로토타입이 동일한 이름을 가진 함수를 복제하지 않을 것이라고 이해할 수 있습니다.
그럼 새로운 질문이 생길 것입니다:
extendClass의 인스턴스를 사용하여 baseClass의 객체 메소드 showMsg를 호출하려면 어떻게 해야 하나요?
전화를 사용하는 것이 정답입니다.
extendClass.prototype = new baseClass(); var instance = new extendClass(); var baseinstance = new baseClass(); baseinstance.showMsg.call(instance);//显示baseClass::showMsg
여기서 baseinstance.showMsg.call(instance)은 "인스턴스를 baseinstance로 호출하고 해당 객체 메소드 showMsg를 호출합니다"라고 읽습니다.
좋아요, 여기 누군가가 baseClass.showMsg.call(instance)을 사용하면 어떨까요?
이것이 객체 메소드와 클래스 메소드의 차이점입니다. 우리가 호출하려는 것은 baseClass의 객체 메소드입니다
마지막으로 다음 코드를 명확하게 이해하면 이 문서의 내용을 이해할 수 있습니다.
<script type="text/javascript"> function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } this.baseShowMsg = function() { alert("baseClass::baseShowMsg"); } } baseClass.showMsg = function() { alert("baseClass::showMsg static"); } function extendClass() { this.showMsg =function () { alert("extendClass::showMsg"); } } extendClass.showMsg = function() { alert("extendClass::showMsg static") } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg(); //显示extendClass::showMsg instance.baseShowMsg(); //显示baseClass::baseShowMsg instance.showMsg(); //显示extendClass::showMsg baseClass.showMsg.call(instance);//显示baseClass::showMsg static var baseinstance = new baseClass(); baseinstance.showMsg.call(instance);//显示baseClass::showMsg </script>
ps: js 프로토타입 속성 설명 및 일반적인 방법
기능: 프로토타입
각 생성자에는 프로토타입이라는 속성이 있습니다(프로토타입은 아래에 번역되지 않으며 원본 텍스트 사용). 이 속성은 특정 클래스에 대한 공통 변수나 함수를 선언하는 데 매우 유용합니다.
프로토타입의 정의
프로토타입 속성은 모든 생성자에 존재하므로 명시적으로 선언할 필요가 없습니다. 다음 예를 살펴보세요.
예제 PT1
코드:
function Test() { } alert(Test.prototype); // 输出 "Object"
프로토타입에 속성 추가
위에서 볼 수 있듯이 프로토타입은 객체이므로 속성을 추가할 수 있습니다. 프로토타입에 추가하는 속성은 이 생성자를 사용하여 생성된 객체의 공통 속성이 됩니다.
예를 들어, 아래에 Fish 데이터 유형이 있고 모든 물고기가 다음 속성을 갖기를 원합니다. 이를 달성하기 위해 해당 속성을 생성자 Fish의 프로토타입에 추가할 수 있습니다.
예제 PT2
코드:
function Fish(name, color) { this.name=name; this.color=color; } Fish.prototype.livesIn="water"; Fish.prototype.price=20;
다음에는 생선을 만들어 보겠습니다.
코드:
var fish1=new Fish("mackarel", "gray"); var fish2=new Fish("goldfish", "orange"); var fish3=new Fish("salmon", "white");
물고기의 속성을 살펴보겠습니다.
코드:
for (int i=1; i<=3; i++) { var fish=eval_r("fish"+i); // 我只是取得指向这条鱼的指针 alert(fish.name+","+fish.color+","+fish.livesIn+","+fish.price); }
출력은 다음과 같아야 합니다.
코드:
"mackarel, gray, water, 20" "goldfish, orange, water, 20" "salmon, white water, 20"
你看到所有的鱼都有属性livesIn和price,我们甚至都没有为每一条不同的鱼特别声明这些属性。这时因为当一个对象被创建时,这个构造函数 将会把它的属性prototype赋给新对象的内部属性__proto__。这个__proto__被这个对象用来查找它的属性。
你也可以通过prototype来给所有对象添加共用的函数。这有一个好处:你不需要每次在构造一个对象的时候创建并初始化这个函数。为了解释这一点,让我们重新来看Example DT9并使用prototype来重写它:
用prototype给对象添加函数
Example PT3
CODE:
function Employee(name, salary) { this.name=name; this.salary=salary; } Employee.prototype.getSalary=function getSalaryFunction() { return this.salary; } Employee.prototype.addSalary=function addSalaryFunction(addition) { this.salary=this.salary+addition; }
我们可以象通常那样创建对象:
CODE:
var boss1=new Employee("Joan", 200000); var boss2=new Employee("Kim", 100000); var boss3=new Employee("Sam", 150000);
并验证它:
CODE:
alert(boss1.getSalary()); // 输出 200000 alert(boss2.getSalary()); // 输出 100000 alert(boss3.getSalary()); // 输出 150000
这里有一个图示来说明prototype是如何工作的。这个对象的每一个实例(boss1, boss2, boss3)都有一个内部属性叫做__proto__,这个属性指向了它的构造器(Employee)的属性prototype。当你执行 getSalary或者addSalary的时候,这个对象会在它的__proto__找到并执行这个代码。注意这点:这里并没有代码的复制(和 Example DT8的图表作一下对比)。