>웹 프론트엔드 >JS 튜토리얼 >JavaScript 프로토타입 및 프로토타입 체인 메서드 소개(코드 예제)

JavaScript 프로토타입 및 프로토타입 체인 메서드 소개(코드 예제)

不言
不言앞으로
2019-01-10 10:59:442750검색

이 기사는 JavaScript 프로토타입 및 프로토타입 체인 메소드(코드 예제)에 대한 소개를 제공합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

1. 질문

변수가 배열인지 정확하게 판별하는 방법

프로토타입 체인 상속의 예를 작성하세요

상속을 구현하는 다른 방법

es6 상속 구현의 기본 원칙은 무엇입니까

설명 새로운 객체 프로세스

zepto 및 기타 소스 코드에서 프로토타입 체인을 사용하는 방법

2. 지식 포인트

2.1 생성자

특징: 대문자로 시작

function Foo(name,age){
    //var obj = {}
    //this = {}
    this.name = name;
    this.age = age;
    this.class = 'class1'
    // return this
}

var f1 = new Foo('liming',19);

Expand

var o = {} is var o = new Object ()

var a = []의 구문은 var a = new Array()

function Foo(){}의 구문이며 이는 var Foo = new Function()과 동일합니다. {}

2.2 프로토타입 규칙

5가지 규칙:

1. 모든 참조 유형(객체, 배열, 함수)에는 객체 특성이 있습니다. 즉, 속성을 자유롭게 확장할 수 있습니다.

2. 배열, 함수)에는 일반 객체

3인 __proto__(암시적 프로토타입) 속성이 있습니다. 모든 함수에는 일반 객체이기도 한 프로토타입(명시적 프로토타입) 속성이 있습니다. , 함수) __proto__ 값은 생성자 프로토타입을 가리킵니다

5. 객체의 속성을 가져오려고 할 때 변수 자체에 이 속성이 없으면 해당 __proto__로 이동하여 해당 객체를 찾습니다.

for (var key in object) {
    //高级浏览器中已经屏蔽了来自原型的属性
    //建议加上判断保证程序的健壮性
    if (object.hasOwnProperty(key)) {
        console.log(object[key]);
    }
}

2.3 프로토타입 체인

obj.__ proto

proto . proto __ ...Object.prototype === null

instanceof는 참조 유형이 속한 생성자를 결정하는 데 사용됩니다. 의미: Foo.prototype이 obj의 프로토타입 체인에 있는지 확인

3. 질문에 대한 답변

3.1 변수가 배열인지 정확하게 확인하는 방법

arr 인스턴스of Array3.2 프로토타입의 예 작성 체인 상속

dom 쿼리 캡슐화

function Elem(id){
    this.elem = document.getElementById(id);
};

Elem.prototype.html = function(val){
    var elem = this.elem;
    if (val) {
        elem.innerHTML = val;
        return this;
    }else{
        return elem.innerHTML;
    }
}

Elem.prototype.on = function(type,fun){
    var elem = this.elem;
    elem.addEventListener(type,fun);
    return this;
}

var p1 = new Elem('id1');
p1.html("test").on('click',function(){
    console.log('点击');
})

3.3 상속 구현의 다른 방법

3.3.1 프로토타입 상속

        var obj = {
            0:'a',
            1:'b',
            arr:[1]
        }
        
        function Foo(arr2){
            this.arr2 = [1]
        }

        Foo.prototype = obj;

        var foo1 = new Foo();
        var foo2 = new Foo();

        foo1.arr.push(2);
        foo1.arr2.push(2);

        console.log(foo2.arr);  //[1,2]
        console.log(foo2.arr2); //[1]

장점: 간단한 구현단점:

1 매개변수를 상위 클래스 생성자에 전달할 수 없습니다.

2. 두 개의 새로운 객체가 동시에 생성되면 한 객체의 프로토타입에 있는 참조 유형의 속성이 변경되고, 다른 객체의 속성도 수정됩니다. 프로토타입 객체의 참조 속성은 모든 인스턴스에서 공유되기 때문입니다.

3.3.2 구조적 상속

        function Super(b){
            this.b = b;
            this.fun = function(){}
        }
        function Foo(a,b){
            this.a = a;
            Super.call(this,b);
        }

        var foo1 = new Foo(1,2);
        console.log(foo1.b);
장점: 매개변수를 상위 클래스에 전달할 수 있으며 하위 클래스는 상위 클래스의 참조 속성을 공유하지 않습니다.

단점: 함수 재사용이 불가능하고 각 하위 클래스에는 새로운 재미가 있습니다. 너무 많으면 성능에 영향을 미치고 상위 클래스의 프로토타입 객체를 상속할 수 없습니다.

3.3.3 조합 상속

function Super(){
    // 只在此处声明基本属性和引用属性
    this.val = 1;
    this.arr = [1];
}
//  在此处声明函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
    Super.call(this);   // 核心
    // ...
}
Sub.prototype = new Super();

장점: 참조 속성을 공유하는 데 문제가 없으며 매개변수를 전달할 수 있고 함수를 재사용할 수 있습니다.

단점: 상위 클래스의 속성이 두 번 인스턴스화되고 실제 인스턴스가 생성됩니다. 부모 클래스를 얻을 수 없음(인스턴스가 부모 클래스에서 생성되었는지, 부모 클래스에서 생성되었는지 구별할 수 없음)

최적화:

         function Super(b){
            this.b = b;
            this.fun = function(){}
        }

        Super.prototype.c = function(){console.log(1111)}

        function Foo(a,b){
            this.a = a;
            Super.call(this,b);
        }


        Foo.prototype = Super.prototype;
        //修复构造函数:
        var foo1 = new Foo(1,2);

단점: 인스턴스가 부모 클래스에서 생성되었는지, 하위 클래스에서 생성되었는지 구별할 수 없음

3.3 .4 기생 조합 상속

         function Super(b){
            this.b = b;
        }

        Super.prototype.c = function(){console.log(1111)}

        function Foo(a,b){
            this.a = a;
            Super.call(this,b);
        }

        var f = new Function();
        f.prototype = Super.prototype;
        Foo.prototype = new f();
        //等同于 Foo.prototype = Object.create(Super.prototype);
        
        var foo1 = new Foo(1,2);
부모 클래스의 프로토타입 한 번 기생합니다. 즉, 이를 빈 객체의 프로토타입으로 래핑한 다음 이 객체를 하위 클래스의 프로토타입으로 인스턴스화합니다.

단점: 인스턴스가 상위 클래스에 의해 생성되었는지 하위 클래스에 의해 생성되었는지 구별이 불가능합니다.

다음 코드를 추가할 수 있습니다.

Foo.prototype.constructor = Foo

위의 결합된 최적화 방법에는 이 솔루션을 사용할 수 없습니다. 클래스가 동일한 프로토타입 객체를 참조하면 수정 사항이 동시에 수정됩니다.

요약:

상속은 주로 하위 클래스별로 상위 클래스 메서드와 속성을 재사용하는 것을 구현합니다.

프로토타입 객체의 참조 속성은 모든 인스턴스에서 공유되므로 프로토타입에서 속성을 상속받는 것을 피하고 싶습니다.

생성자의 호출 함수를 통해 부모 클래스 생성자의 속성과 메서드를 상속받을 수 있지만, 이렇게 인스턴스화된 인스턴스는 부모 클래스 메서드를 여러 번 저장하게 되어 성능에 영향을 미칩니다.

결합 상속을 통해 호출 상속 속성을 사용하고 프로토타입 상속 방법을 사용하여 위의 두 가지 문제를 해결하지만, 이런 방식으로 인스턴스화된 객체는 부모 클래스 생성자에 속성의 복사본 두 개를 저장하게 됩니다.

부모 클래스의 프로토타입을 하위 클래스의 프로토타입으로 사용하여 새 객체를 생성하면 다중 저장 문제가 해결되므로 최종 기생 조합 상속이 가장 좋은 상속 방법이지만 작성이 더 번거롭다는 단점이 있습니다.

3.3.6 노드 소스 코드에서 상속 구현

function inherits(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
}; 

function Stream(){
    //...
}

function OutgoingMessage() {
  Stream.call(this);
  //...
}

inherits(OutgoingMessage, Stream);

OutgoingMessage.prototype.setTimeout = ...
위는 기생 조합 상속의 예입니다.

1. OutgoingMessage 생성자의 호출을 통해 Stream 생성자의 속성을 상속합니다.

2. Stream 프로토타입의 속성을 상속하려면 상속 메서드를 호출하세요.

3. OutgoingMessage의 자체 프로토타입을 확장하는 기능입니다.

inherites 메소드에는 Object.create 메소드가 사용됩니다. 이 메소드의 기능은 지정된 프로토타입 객체와 속성을 통해 새로운 객체를 생성하는 것입니다.

ctor.prototype=Object.create(superCtor.prototype,{.....});
이 메소드는 실제로 위의 기생 조합 상속 작업을 수행합니다.

var f = new Function();
f.prototype =superCtor.prototype;
return new f();
다음 매개변수는 프로토타입 객체에 속성을 추가하는 데 사용되며, 선택적 속성(필수는 아님), 즉 새로 생성된 객체의 생성자로 자신을 사용합니다. .

value: 表示constructor 的属性值;
writable: 表示constructor 的属性值是否可写;[默认为: false]
enumerable: 表示属性constructor 是否可以被枚举;[默认为: false]
configurable: 表示属性constructor 是否可以被配置,例如 对obj.a做 delete操作是否允许;[默认为: false]
3.4 es6 상속을 구현하는 방법

내 기사를 참조하세요: https://segmentfault.com/a/11...

3.5 描述new一个对象的过程

  1. 创建一个对象

  2. {}._proto_ = 构造函数.prototype

  3. this指向这个对象

  4. 执行代码即对this赋值

  5. 返回this

3.6 zepto及其他源码中如何使用原型链

var Zepto = (function(){

    var $,zepto = {}
    
    // ...省略N行代码...
    
    $ = function(selector, context){
        return zepto.init(selector, context)
    }

    zepto.init = function(selector, context) {
        var dom
        
        // 针对参数情况,分别对dom赋值
        
        // 最终调用 zepto.Z 返回的数据
        return zepto.Z(dom, selector)
    }    

   fnction Z(dom, selector) {
      var i, len = dom ? dom.length : 0
     for (i = 0; i < len; i++) this[i] = dom[i]
      this.length = len
      this.selector = selector || ''
    }

   zepto.Z = function(dom, selector) {
     return new Z(dom, selector)
   }
  
    $.fn = {
        // 里面有若干个工具函数
    }
      
  
    zepto.Z.prototype = Z.prototype = $.fn
  
    
    // ...省略N行代码...
    
    return $
})()

window.Zepto = Zepto
window.$ === undefined && (window.$ = Zepto)

위 내용은 JavaScript 프로토타입 및 프로토타입 체인 메서드 소개(코드 예제)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제