js объектно-ориентированное резюме

внешний интерфейс JavaScript
js объектно-ориентированное резюме

Объектно-ориентированное программирование (ООП)

В последнее время я чувствую, что не знаю, чему учиться. Я всегда чувствую, что ничего не знаю, но я также чувствую, что могу чему-то научиться. Даже если я говорю «да», я также знаю объектно-ориентированное. не получил очень систематического понимания, поэтому я взглянул на точки знаний здесь.Когда я был своим собственным носильщиком, я делал вид, что публикую статью, и ждал, пока это будет удобно для меня;

создать объект

1. Фабричный шаблон: инкапсулируйте с помощью функций, создавайте детали объектов с определенными интерфейсами.

  1. Решена проблема создания нескольких одинаковых объектов,
  2. В основном он используется для создания нескольких объектов с одинаковыми свойствами и методами, чтобы избежать дублирования кода;
  3. Не решает проблему идентификации объекта (то есть как узнать тип объекта) (его instanceof может быть только Object)
   function creatPerson(name,age,job) {
        var o = new Object();
        o.name= name;
        o.age= age;
        o.job= job;
        o.sayName = function(){
            alert(this.name);
        };
        return o;
    }
    var p1 = creatPerson("hh",23,"worker");
    var p2 = creatPerson("xx",26,"worker1");
    p1.__proto__===p2.__proto__===Object.prototype;

    对象的constructor 属性最早是用来描述队形类型的,检测对象类型还是 instanceof 更可靠
    工厂模式创建的对象,constructor只有Object,这样的实例没有特定的类型;

2. Шаблон конструктора:

  1. Решить проблему распознавания объектов (т.е. как узнать тип объекта)
  2. Недостаток: каждый метод воссоздается один раз в каждом экземпляре, p1.sayName!=p2.sayName в следующем каштане.
  3. Решение: выдвинуть конструктор, объявить глобальную функцию записи (недостаток этого решения: глобальная функция вызывает только локальные вызовы, слишком много методов приходится создавать несколько глобальных функций, пакета вообще нет);
    function Person(name,age,job){
        this.age = age;
        this.name = name;
        this.job = job;
        this.sayName = function(){
            alert(this.name)
        }
        //this.sayName = sayName;   //解决方式
    }
    var p1 = new Person("hh",23,"worker");
    var p2 = new Person("xx",26,"worker1");
        
        //function sayName(){alert(this.name)}  //解决方式


    new的执行:
        {
            var obj ={};
            obj.__proto__ = Person.prototype;
            Person.call(obj);
            return obj
        }
    p1 instanceof Person //true;
    p2 instanceof Person //true;
    p1 instanceof Object //true;
    p2 instanceof Object //true;
    这样是得p1和p2实例有了特定的类型, Person;

3. Режим прототипа

  1. Преимущества: Он опускает ссылку на параметры инициализации конструктора, все свойства в прототипе являются общими для многих экземпляров, совместное использование очень подходит для функций, и базовые свойства также в порядке. Добавляя в экземпляр свойство с тем же именем, можно скрыть соответствующее значение свойства в прототипе;

  2. Недостатки: Его общие свойства не влияют на свойства, содержащие значения ссылочного типа, если экземпляр переназначается.Как и базовые типы, если это модификация операции, есть некоторые проблемы, которые сделают свойства, полученные всеми экземплярами, измененными, так что он также не используется в одиночку

        function Person(){}
        Person.prototype={
            constructor:Person,
            name:"ss",
            friends:["s1","s2"],
            sayName:function(){alert(this.name)}
        }
        var p1= new Person();
        var p2= new Person();
        p1.name = "p1"
        console.log(p1.name) //p1
        console.log(p2.name) //ss
        p1.friends.push("s3");
        console.log(p1.friends) //["s1","s2","s3"]
        console.log(p2.friends) //["s1","s2","s3"]
    
  3. Применение:

    1. Общее использование:
          function Person(){}
          Person.prototype.name="ceshi"
          Person.prototype.age =12;
          Person.prototype.sayName = function(){
              alert(this.name)
          }
          //这样就是实现了代码的共享
      
      
    2. простое письмо
      
          更简单的写法:
              Person.prototype={
                  //constructor:Person,
                  name:"test",
                  age:12,
                  sayName:function(){alert(this.name)}
              }
          var friend = new Person();
          friend instanceof Object //true
          friend instanceof Person //true
          friend.constructor==Person //false
          friend.constructor==Object //true
      
          这种简单的写法constructor 属性就不在指向Person,而是指向Object构造函数;
          此时可以添加一个属性constructor( 如上面注释):但是此时的constructor 变成了可枚举的属性,原生是不可枚举的,可以考虑用Object.defineProperty()
      
      
    3. Динамика прототипа:
          var p1 = new Person();
          <!-- 1 -->
              Person.prototype.hh="ss";
              p1.hh//ss 是可以先创建实例在改边原型在访问的;
              
          <!-- 2 -->
              Person.prototype={
                  name:"ss"
              }
              p1.__proto__!=Person.prototype;
              p1.name // undefined 
      
      
    4. Прототип нативного объекта:
      1. Вы можете добавить методы модификации к родным ссылочным типам (Object, Array, String...)
        String.prototype.strarWith=function(tesx){return this.indexOf(text)==0}

4. Объединение шаблона конструктора и шаблона прототипа: (Определить шаблон по умолчанию для ссылочных типов)

  1. Шаблон конструктора используется для определения свойств экземпляра; каждое свойство воссоздается один раз для каждого экземпляра; даже изменение ссылочных типов не влияет на другие экземпляры.
  2. Шаблон прототипа используется для определения методов и общих свойств;
    function Person(age,name){
        this.name = name;
        this.age = age;
        this.friends=[1,2,3]
    }
    Person.prototype={
        constructor:Person,
        sayName:function(){
            alert(this.name)
        }
    }
    var p1 = new Person("ss",12);
    var p2 = new Person("ss3",123);
    p1.friends.push(2);
    console.log(p1.friends) // [1,2,3,2]
    console.log(p2.friends)// [1,2,3]

5. Режим динамического прототипа:

  1. Прототип и функция папарацци независимы, что отличается от ОО в других языках.Динамический прототип должен инкапсулировать всю информацию в конструкторе;
  2. В конструкторе проверить, допустим ли метод, который следует использовать, подумать, инициализирован ли прототип, на самом деле это инициализировать прототип один раз

    function Person(name,age){
        this.name = name;
        this.age = age;
        if(typeof this.sayName !="function"){//sayName没初始化 这里对一个方法判断就可以,然后初始化所有的,没必要都每个方法都判断

            Person.prototype.sayName=function(){alert(this.name)}
            Person.prototype.sayAge=function(){alert(this.age)};
            .....
        }
  ****注意****:此处不能使用对象字面量形式重写原型, 因为这中写法是先创建的实例,然后在修改的原型,要是用对象字面量重写原型,会切断现有实例和新原型之间的联系, 导致方法实例上无此方法;
    }

6. Шаблон паразитного конструктора:

  1. Аналогичен фабричному шаблону, но использует new для инициализации экземпляра;
  2. Возвращаемый объект не имеет ничего общего с конструктором и прототипом конструктора;
    function Person(name,age){
        var o = new Object();
        o.name=name;
        o.age=age;
        o.sayName=function(){
            alert(this.name)
        };
        return o;
    }
    var friends = new Person("xiaoming",12)
    friends.asyName()  // xiaoming

7. Шаблон безопасного конструктора:

Безопасный объект: объект, который не имеет общедоступных свойств и чьи методы не ссылаются на это;

function Person(name,age){
        var o = new Object();
        o.sayName=function(){
            alert(name)
        };
        return o;
    }
    var friends = new Person("xiaoming",12)
    friends.asyName()  // xiaoming

Наследовать:

  1. Наследование обычно включает в себя: Наследование интерфейса: наследовать методы и сигнатуры; Наследование реализации: наследуйте фактический метод; ECMAScript поддерживает только наследование реализации.

  2. js в основном реализует наследование через цепочку прототипов, построение цепочки прототипов реализуется путем присвоения экземпляра одного типа прототипу другого конструктора.

Наследование

1. Цепочка-прототип (редко используется отдельно)
  1. Проблема: данные ссылочного типа манипулируются (переназначение не влияет на него, что эквивалентно добавлению скрытого родительского класса в подкласс), которые будут общими для всех экземпляров.
  2. Проблема: при создании подкласса нельзя передавать параметры в конструктор родительского класса; ? ?
    Son.prototype = new Father();
    
    //此时Son.constructor 被改写为了 Father;
    Son.prototype.constructor = Son;
    
    //给子类修改或者是添加方法的时候,要放在替换语句,改版子类原型语句之后, 
    //原型继承时,不能使用字面量方式创建原型方法,这样就重新写了原型链了
    Son.prototype.getName=function(){alert(this.name)};

2. Привязка конструктора: вызов, применение Наследование: (редко используется отдельно)
  1. Проблема: Метод в прототипе родительской функции (прототип), подкласс не виден
  2. Проблемный кролик: атрибуты метода определены в конструкторе, каждый экземпляр и метод пересоздаются один раз, повторного использования нет z
    function Son(){
        Father.call(this,arguments)
    }
3. Комбинированное наследование: (общий образец наследования)
  1. Таким образом, экземпляры могут иметь свои собственные свойства (включая ссылочные типы, дополнительные эффекты между экземплярами) и могут использовать один и тот же метод;
  2. Недостаток: в любом случае конструктор родительского класса будет вызываться дважды;
    function Father(){
        this.name ="ss";
        this.friends=[1,2,3,4]
    }
    function Son(){
        Father.call(this);
    }
    Son.prototype = new Father(); // Son 原型获得Father上的属性,name和friends


    var son1 = new Son(); // 此时调用Son构造函数为son1 实例上添加了属性(name和friends), 这些属性就屏蔽了原型中的同名属性;
    // 调用两次Father构造函数的结果就是有两组属性,一组在实例上,一组在原型上;

4. Прототипное наследование:
  1. В случае, когда нет необходимости создавать конструктор, а просто хочется, чтобы один объект был похож на другой объект, можно использовать его, аналогичный денежной копии;
    function object(o){
        function F(){};
        F.prototype = o;
        return new F();
    }
    // 和 Object.creat() 传递一个参数时候相同
5. Паразитическое наследование:
  1. Наследовать свойства и методы происхождения;
  2. Также имеет свой собственный метод;
    function creat(origin){
        var clone = object(origin); // 可以是任何返回新对象的函数
        clone.sayName(){alert("name")}; //这里的函数每次都创建,不存在复用一说,
        return clone;
    }
6. Паразитическая композиция: (идеальная реализация наследования)
  1. Устраните дефекты комбинированного наследования, создайте два набора свойств и создайте прототипы только для экземпляров;
  2. Наследовать свойства через конструкторы и наследовать методы через смешанную форму цепочки прототипов (то есть назначать копию родительского класса прототипу подкласса).
    function inherit(son,father){

        var prototype = object(father.prototype); 
            // 上句话,创建父类原型的副本,prototype.__proto__ = Father.prototype;
            // prototype 继承constructor prototype.constructor 取的是原型链上,原型的Father.prototype.constructor, 为 Father();即:prototype.constructor == prototype.__proto__.constructor  // true
            // prototype.hasOwnPrototyoe("constructor") //false
        

        prototype.constructor = son; // 弥补重写原型造成的默认属性的修改;
            //此时是给prototype 添加了constructor 属性,赋值为son, 屏蔽了原型上的constructor属性
            // prototype.hasOwnPrototype("constructor") // true
            // prototype.constructor = son;
            // prototype.__proto__.constructor = father
        son.prototype  = prototype;
            // 给子类原型赋值为父类原型的副本;
    }

    //使用:
    function Father(){
        this.name="11";
        this.age=12;
    }
    Father.prototype.sayName=function(){
        alert(this.name);
    }
    function Son(){
        Father.call(this);
        this.age=23;
    }
    inherit(Son,Father);
    Son.prototype.sayAge=function(){
        alert(this.age)
    }