찾다
웹 프론트엔드JS 튜토리얼javascript 프레임워크 디자인 및 기타 Factory_javascript 기술

JavaScript에서 클래스와 상속의 출현은 JavaScript가 대규모 개발의 문턱에 도달했음을 보여줍니다. ECMAScript 4 이전에는 클래스, 모듈 등을 도입하려고 시도했지만 너무 많은 도입으로 인해. 기능 때문에 JavaScript가 엉망이 되어 거부당했습니다. 하지만 ES6으로의 클래스가 지연될 뿐입니다. 지금까지 JavaScript에는 실제 클래스가 없습니다. 그러나 최근에는 클래스 팩토리가 프레임워크의 표준 기능이 되었습니다. 이 장에서는 모든 사람이 자신의 프레임워크에서 원하는 스타일을 쉽게 선택할 수 있도록 다양한 클래스 구현을 소개합니다.

1.수업에 대한 자바스크립트 지원

다른 언어에서는 클래스의 인스턴스가 new 생성자를 통해 생성되어야 합니다. 의도적으로 Java를 모방한 언어입니다. JavaScript에는 새로운 연산자가 있으며 모든 함수를 생성자로 사용할 수 있습니다. 생성자는 일반적인 방법과 다르지 않습니다. Node, Element, HTMLElement 및 HTMLParagraphElement와 같은 번성하는 생태계를 구축하기 위해 브라우저는 분명히 상속 관계를 사용하여 일부 메서드나 속성의 공유를 용이하게 하므로 JavaScript는 다른 언어에서 프로토타입 메커니즘을 차용합니다. 프로토타입은 모든 기능에 대한 특별한 객체 속성으로 존재합니다. 함수가 new 연산자를 사용하여 "자식" - "인스턴스"를 생성하면 인스턴스라는 이름의 이 객체는 이 함수의 프로토타입 객체의 모든 멤버를 가지므로 모든 인스턴스 객체가 메서드 또는 속성 집합을 공유한다는 것을 인식합니다. JavaScript에서 소위 "클래스"는 이 프로토타입 개체를 수정하여 기본 개체를 정의된 다른 "클래스"와 구별하는 것입니다. 브라우저에서는 Node 클래스는 Object를 기반으로 수정되고 Element는 Node를 기반으로 하며 HTMLElement는 Element를 기반으로 수정됩니다.... 업무에 비해 자체 클래스를 생성하여 재사용 및 공유가 가능합니다.

  function A(){

  }
  A.prototype = {
    aa:"aa",
    method:function(){
    }
  };
  var a = new A;
  var b = new A;
  console.log(a.aa === b.aa);
  console.log(a.method === b.method)

일반적으로 프로토타입에 정의된 메소드를 모든 인스턴스가 공유하는 프로토타입 메소드라고 부릅니다. 이는 좋은 점이기도 하고 나쁜 점이기도 합니다. JavaScript에서는 생성자에서 해당 메소드를 직접 지정할 수 있습니다. 권한 있는 방법이라고 합니다. 속성인 경우 권한 있는 속성이라고 합니다. 각 인스턴스에는 복사본이 있으며 서로 영향을 받지 않습니다. 따라서 우리는 일반적으로 프로토타입에 데이터를 운용하기 위한 공유 메소드를 넣고, 특권 속성에 프라이빗 속성을 넣습니다. 하지만 이렇게 올려놓으면 여전히 마음대로 접근이 가능하므로 함수 본문의 범위에 넣습니다. 이 시점에서 그것은 진정한 사유 재산이 됩니다.

  function A() {
    var count = 0;
    this.aa = "aa";
    this.method = function() {
      return count;
    }
    this.obj = {}
  }
  A.prototype = {
    aa:"aa",
    method:function(){

    }
  };
  var a = new A;
  var b = new A;
  console.log(a.aa === b.aa);//true 由于aa的值为基本类型,比较值
  console.log(a.obj === b.obj) //false 引用类型,每次进入函数体都要重新创建,因此都不一样。
  console.log(a.method === b.method); //false

권한 있는 메서드 또는 속성은 프로토타입 메서드 또는 속성에만 적용되므로 권한 있는 메서드를 삭제하는 한 동일한 이름을 가진 프로토타입 메서드 또는 속성에 액세스할 수 있습니다.

  delete a.method;
  delete b.method;
  console.log(a.method === A.prototype.method);//true
  console.log(a.method === b.method); //true

Java 언어에서는 프로토타입 메소드와 특권 메소드 모두 인스턴스 메소드의 속성입니다. Java에는 클래스 메소드와 클래스 속성이라는 것이 있습니다. JavaScript를 사용하여 시뮬레이션하는 것은 매우 간단합니다. 함수에서 직접 정의하기만 하면 됩니다.

  A.method2 = function(){} //类方法
  var c = new A;
  console.log(c.method2); //undefined

다음으로 상속 구현을 살펴보겠습니다. 위에서 언급한 것처럼 프로토타입에 있는 것이 무엇이든 인스턴스에는 이 속성이 나중에 추가되거나 전체 프로토타입이 교체되는 등의 무언가가 있습니다. 이 프로토타입 객체를 다른 클래스의 프로토타입으로 바꾸면 해당 클래스의 모든 프로토타입 멤버를 쉽게 얻을 수 있습니다.

  function A() {};
  A.prototype = {
    aaa : 1
  }
  function B() {};
  B.prototype = A.prototype;
  var b = new B;
  console.log(b.aaa); //=> 1;
  A.prototype.bb = 2;
  console.log(b.bb) //=> 2;

동일한 객체를 참조하므로 A 클래스의 프로토타입을 수정하면 B 클래스의 프로토타입을 수정하는 것과 같습니다. 따라서 하나의 객체를 두 클래스에 할당할 수 없습니다. 두 가지 방법이 있습니다.

방법 1:
에서 for를 통해 상위 클래스의 프로토타입 멤버를 하위 클래스의 프로토타입에 하나씩 할당합니다. 방법 2는: 하위 클래스의 프로토타입을 상위 클래스에서 직접 가져오지 않는 것입니다. 먼저 상위 클래스의 프로토타입을 함수에 할당한 다음 이 함수의 인스턴스를 하위 클래스의 프로토타입으로 사용합니다.

첫 번째 방법은 일반적으로 일부 책에서 복사 상속이라고 부르는 mixin과 같은 방법을 구현해야 합니다. 장점은 간단하고 직접적이지만 단점은 검증 인스턴스를 통과할 수 없다는 것입니다. 이를 위해 Prototype.js의 확장 메소드가 사용됩니다.

  function extend (des, source) { //des = destination
    for (var property in source)
      des[property] = source[property];
    return des;
  }

두 번째 방법은 프로토타입에 두뇌를 사용하는 것이므로 프로토타입 상속이라고 합니다. 아래는 템플릿입니다

  function A() {};
  A.prototype = {
    aa:function(){
      alert(1)
    }
  }
  function bridge() {

  };
  bridge.prototype = A.prototype;

  function B() {}
  B.prototype = new bridge();

  var a = new A;
  var b = new B;

  console.log(a == b) //false 证明成功分开原型
  console.log(A.prototype == B.prototype) //true 子类共享父类的原型方法
  console.log(a.aa === b.aa); //为父类动态添加新的方法
  A.prototype.bb = function () {
    alert(2)
  }
  //true,继承父类的方法
  B.prototype.cc = function (){
    alert(3)
  }
  //false 父类未必有子类的new实例
  console.log(a.cc === b.cc)
  //并且它能够正常通过javascript自带的验证机制instanceof
  console.log(b instanceof A) ;//true
  console.log(b instanceof B) ; //true

방법 2는 인스턴스 검증을 통과할 수 있습니다. es5에는 프로토타입 상속을 구현하기 위해 이 방법이 내장되어 있습니다. 두 번째 매개변수를 고려하지 않으면 대략 다음 코드와 같습니다.

  Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
  }

위 메소드에서는 상위 클래스의 프로토타입을 매개변수로 전달한 다음 하위 클래스의 프로토타입을 반환해야 합니다.

그러나 우리는 여전히 뭔가를 놓치고 있습니다. 하위 클래스는 상위 클래스의 상속을 상속받을 뿐만 아니라 자체적인 것도 가지고 있습니다. 게다가 프로토타입 상속은 하위 클래스가 상위 클래스의 멤버 및 권한 있는 멤버를 상속하는 것을 허용하지 않습니다. . 클래스 멤버와 같은 이들을 수동으로 추가해야 하며 위의 확장 메서드를 사용할 수 있으며 권한이 있는 멤버는 적용을 통해 하위 클래스 생성자에서 구현할 수 있습니다.

  function inherit(init, Parent, proto){
    function Son(){
      Parent.apply(this, argument); //先继承父类的特权成员
      init.apply(this, argument); //在执行自己的构造器
    }
  }
  //由于Object.create是我们伪造的,因此避免使用第二个参数
  Son.prototype = Object.create(Parent.prototype,{});
  Son.prototype.toString = Parent.prototype.toString; //处理IEbug
  Son.prototype.valueOf = Parent.prototype.valueOf; //处理IEbug
  Son.prototype.constructor = Son; //确保构造器正常指向,而不是Object
  extend(Son, proto) ;//添加子类的特有的原型成员
  return Son;

下面,做一组实验,测试下实例的回溯机制。当我们访问对象的一个属性,那么他先寻找其特权成员,如果有同名就返回,没有就找原型,再没有,就找父类的原型...我们尝试将它的原型临时修改下,看它的属性会变成那个。

  function A(){

  }
  A.prototype = {
    aa:1
  }
  var a = new A;
  console.log(a.aa) ; //=>1

  //将它的所有原型都替换掉
  A.prototype = {
    aa:2
  }
  console.log(a.aa); //=>1

  //于是我们想到每个实例都有一个constructor方法,指向其构造器
  //而构造器上面正好有我们的原型,javascript引擎是不是通过该路线回溯属性呢
  function B(){

  }
  B.prototype = {
    aa:3
  }
  a.constructor = B;
  console.log(a.aa) //1 表示不受影响

因此类的实例肯定通过另一条通道进行回溯,翻看ecma规范可知每一个对象都有一个内部属性[[prototype]],它保存这我们new它时的构造器所引用的Prototype对象。在标准浏览器与IE11里,它暴露了一个叫__proto__属性来访问它。因此,只要不动__proto__上面的代码怎么动,a.aa始终坚定不毅的返回1.

再看一下,new时操作发生了什么。

1.创建了一个空对象 instance
2.instance.__proto__ = intanceClass.prototype
3.将构造函数里面的this = instance
4.执行构造函数里的代码
5.判定有没有返回值,没有返回值就返回默认值为undefined,如果返回值为复合数据类型,则直接返回,否则返回this
于是有了下面的结果。

  function A(){
    console.log(this.__proto__.aa); //1
    this.aa = 2
  }
  A.prototype = {aa:1}
  var a = new A;
  console.log(a.aa)
  a.__proto__ = {
    aa:3
  }
  console.log(a.aa) //=>2
  delete a. aa; //删除特权属性,暴露原型链上的同名属性
  console.log(a.aa) //=>3

有了__proto__,我们可以将原型设计继承设计得更简单,我们还是拿上面的例子改一改,进行试验

  function A() {}
  A.prototype = {
    aa:1
  }
  function bridge() {}
  bridge.prototype = A.prototype;

  function B(){}
  B.prototype = new bridge();
  B.prototype.constructor = B;
  var b = new B;
  B.prototype.cc = function(){
    alert(3)
  }
  //String.prototype === new String().__proto__ => true
  console.log(B.prototype.__proto__ === A.prototype) //true
  console.log(b.__proto__ == B.prototype); //true 
  console.log(b.__proto__.__proto__ === A.prototype); //true 得到父类的原型对象

因为b.__proto__.constructor为B,而B的原型是从bridge中得来的,而bride.prototype = A.prototype,反过来,我们在定义时,B.prototype.__proto__ = A.prototype,就能轻松实现两个类的继承.

__proto__属性已经加入es6,因此可以通过防止大胆的使用

2.各种类工厂的实现。

上节我们演示了各种继承方式的实现,但都很凌乱。我们希望提供一个专门的方法,只要用户传入相应的参数,或按照一定简单格式就能创建一个类。特别是子类。

由于主流框架的类工厂太依赖他们庞杂的工具函数,而一个精巧的类工厂也不过百行左右

相当精巧的库,P.js

https://github.com/jiayi2/pjs

使用版:https://github.com/jiayi2/factoryjs

这是一个相当精巧的库,尤其调用父类的同名方法时,它直接将父类的原型抛在你面前,连_super也省了。

  var P = (function(prototype, ownProperty, undefined) {
 return function P(_superclass /* = Object */, definition) {
  // handle the case where no superclass is given
  if (definition === undefined) {
   definition = _superclass;
   _superclass = Object;
  }

  // C is the class to be returned.
  //
  // When called, creates and initializes an instance of C, unless
  // `this` is already an instance of C, then just initializes `this`;
  // either way, returns the instance of C that was initialized.
  //
  // TODO: the Chrome inspector shows all created objects as `C`
  //    rather than `Object`. Setting the .name property seems to
  //    have no effect. Is there a way to override this behavior?
  function C() {
   var self = this instanceof C ? this : new Bare;
   self.init.apply(self, arguments);
   return self;
  }

  // C.Bare is a class with a noop constructor. Its prototype will be
  // the same as C, so that instances of C.Bare are instances of C.
  // `new MyClass.Bare` then creates new instances of C without
  // calling .init().
  function Bare() {}
  C.Bare = Bare;

  // Extend the prototype chain: first use Bare to create an
  // uninitialized instance of the superclass, then set up Bare
  // to create instances of this class.
  var _super = Bare[prototype] = _superclass[prototype];
  var proto = Bare[prototype] = C[prototype] = C.p = new Bare;

  // pre-declaring the iteration variable for the loop below to save
  // a `var` keyword after minification
  var key;

  // set the constructor property on the prototype, for convenience
  proto.constructor = C;

  C.extend = function(def) { return P(C, def); }

  return (C.open = function(def) {
   if (typeof def === 'function') {
    // call the defining function with all the arguments you need
    // extensions captures the return value.
    def = def.call(C, proto, _super, C, _superclass);
   }

   // ...and extend it
   if (typeof def === 'object') {
    for (key in def) {
     if (ownProperty.call(def, key)) {
      proto[key] = def[key];
     }
    }
   }

   // if no init, assume we're inheriting from a non-Pjs class, so
   // default to using the superclass constructor.
   if (!('init' in proto)) proto.init = _superclass;

   return C;
  })(definition);
 }

 // as a minifier optimization, we've closured in a few helper functions
 // and the string 'prototype' (C[p] is much shorter than C.prototype)
})('prototype', ({}).hasOwnProperty);

我们尝试创建一个类:

  var Dog = P (function(proto, superProto){
    proto.init = function(name) { //构造函数
      this.name = name;
    }
    proto.move = function(meters){ //原型方法
      console.log(this.name + " moved " + meters + " m.")
    }
  });
  var a = new Dog("aaa")
  var b = new Dog("bbb"); //无实例变化
  a.move(1);
  b.move(2);

我们在现在的情况下,可以尝试创建更简洁的定义方式

  var Animal = P (function(proto, superProto){
    proto.init = function(name) { //构造函数
      this.name = name;
    }
    proto.move = function(meters){ //原型方法
      console.log(this.name + " moved " + meters + " m.")
    }
  });
  var a = new Animal("aaa")
  var b = new Animal("bbb"); //无实例变化
  a.move(1);
  b.move(2);
  //...............
  var Snake = P (Animal, function(snake, animal){
    snake.init = function(name, eyes){
      animal.init.call(this, arguments); //调运父类构造器
      this.eyes = 2;
    }
    snake.move = function() {
      console.log('slithering...');
      animal.move.call(this, 5); //调运父类同名方法
    }
  });
  var s = new Snake("snake", 1);
  s.move();
  console.log(s.name);
  console.log(s.eyes);

私有属性演示,由于放在函数体内集中定义,因此安全可靠!

  var Cobra = P (Snake, function(cobra){
    var age = 1;//私有属性
    //这里还可以编写私有方法
    cobra.glow = function(){ //长大
      return age++;
    }
  });
  var c = new Cobra("cobra");
  console.log(c.glow()); //1
  console.log(c.glow()); //2
  console.log(c.glow()); //3

以上所述就是本文的全部内容了,希望大家能够喜欢。

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전