Пакет JS, который вы можете увидеть с первого взгляда 💐

JavaScript
Пакет JS, который вы можете увидеть с первого взгляда 💐

👣👣 Три основные особенности JS всегда были трудны для понимания. Многие новички и даже опытные начальники могут не говорить внятно. Большинство из них понимаются лишь наполовину, и эта часть контента является основным содержанием JS. Итак, недавно я резюмировал эту статью об инкапсуляции JS и буду публиковать статьи о наследовании JS одну за другой. Надеюсь, это могло помочь всем. 😄

Я надеюсь, что друзья, которые кликнули, могут поставить лайк 👍, ваша поддержка - самая большая поддержка для меня 💪! ! !

Что ж, вернемся к делу,

Поехали! 💪💪

основная концепция

"упаковка"Инкапсулируйте объективные вещи в абстрактные классы, спрячьте свойства и методы и открывайте только интерфейсы для внешнего мира.

взять каштан🌰

Инкапсуляция — это превращение части вещей в компонент.

Чтобы сделать очень простой пример, некоторым людям не нужен корпус для использования компьютера, а материнская плата, память, видеокарта и блок питания выставлены наружу.Он считает, что это хорошо и может рассеивать тепло. Но большинство людей по-прежнему упаковывают все свое оборудование в кейс. Преимущества в том, что первый прост в использовании везде, второй имеет полное включение внутренних компонентов, а третий заключается в том, чтобы все инкапсулировать, оставив только несколько интерфейсов, usb, дисплей, аудиоинтерфейс и т. д., что позволяет пользователям Удобнее и понятнее для сопровождающих.

"частные свойства и методы": доступен только внутри конструктора и не может быть доступен извне (свойства, объявленные с помощью var внутри конструктора);

"Общедоступные свойства и методы (или методы экземпляра):"Доступ к свойствам и методам объекта можно получить извне объекта (используйте это в конструкторе или задайте его в объекте-прототипе конструктора, таком как Person.prototype.xxx);

"Статические свойства и методы:"Методы, определенные на конструкторах (такие как Person.xxx), могут быть вызваны без экземпляра;

Упаковка до ES6

Функция (функция) — простейший пакет

"Предисловие:"Прежде всего, первый вопрос, является ли функция своего рода инкапсуляцией? Конечно упаковано. В книге "Advanced JavaScript Programming" написано:

Функции являются центральным понятием любого языка. Любое количество операторов может быть инкапсулировано с помощью функций и может вызываться и выполняться в любом месте и в любое время.

"Как инкапсулировать:"Запишите разрозненные операторы в фигурные скобки функции, чтобы они стали телом функции, а затем вы можете вызвать ее.

"Развернутый код:"

var oDiv = document.getElementsByTagName("div")[0];
var p = document.createElement("p");
body.style.backgroundColor = "green";
p.innerText ="我是新增的标签内容"; oDiv.appendChild(p);

❎ Недостатки:

  • Этот код выполняется каждый раз, что приводит к пустой трате ресурсов
  • Используется для перезаписи переменными с тем же именем - поскольку он объявлен в глобальной области видимости, его легко перезаписать переменными с тем же именем.

"Инкапсулированный код:"

function createTag() {
  var oDiv = document.getElementsByTagName("div")[0];
  var p = document.createElement("p");
  body.style.backgroundColor = "green";
  p.innerText = "我是新增的标签内容";
  oDiv.appendChild(p);
}

✅ Преимущества:

  • улучшить возможность повторного использования кода;
  • Выполните спрос - когда парсер гласит это, функция не будет выполнена немедленно, только когда она называется
  • Избегайте глобальных переменных - потому что есть проблема с ролью функции

Примитивный режим для создания объектов-экземпляров

Если рассматривать человека как объект, то есть 2 атрибута имени и пола;

 var person = {
    name: '',
    sex: ''
  }

Мы генерируем 2 экземпляра объекта в соответствии со свойствами объекта:

var P1 = {};
P1.name = 'Jack';
P1.sex = 'boy';
var P2 = {};
P2.name = 'lisa';
P2.sex = 'girl'

Ну, это самый простой пакет.

Вы обнаружили, что у этого способа есть 2 основных недостатка:

  • Чтобы сгенерировать несколько экземпляров, писать очень хлопотно, код повторяется, а это все равно один и тот же объект
  • Между экземпляром и прототипом нет связи;

Улучшения исходного режима — заводской режим

function Person(name, sex) {
return { name, sex }
}
let p1 = new Person('Jack','boy');
let p2 = new Person('lisa','girl');
console.log(p1) //{name: "Jack", sex: "boy"}
console.log(p2) //{name: "lisa", sex: "girl"}

✅ Преимущества: Решить проблему дублирования кода.

❎ Недостаток: нет внутренней связи между p1 и p2, что не означает, что они являются экземплярами одного и того же объекта-прототипа.

Шаблон конструктора

Так называемый "конструктор" на самом деле является обычной функцией, но эта переменная используется внутри. Использование оператора new в конструкторе создает экземпляр, а переменная this привязывается к объекту экземпляра.

НапримерPersonОбъект-прототип записывается следующим образом:


function Person(name, sex) {
  this.name = name;
  this.sex = sex;
}

Теперь можно создать экземпляр:


let p1 = new Person('Jack','boy');
let p2 = new Person('lisa','girl');
console.log(p1) //{name: "Jack", sex: "boy"}
console.log(p2) //{name: "lisa", sex: "girl"}

constructorЭто свойство объекта-прототипа конструктора, которое обычно указывает на объект-прототип Person.

В этом случае p1 и p2 автоматически будут содержатьconstructorсвойства, указывая на их конструкторы.

alert(p1.constructor == Person); //true
alert(p2.constructor == Person); //true

instanceofОператор используется для определения того, присутствует ли свойство прототипа конструктора в прототипе экземпляра объекта.

Применение:object instanceof constructor

объект: относится к экземпляру объекта;

конструктор: конструктор;

Оператор instanceof используется, чтобы проверить, существует ли в цепочке прототипов объекта параметра, конструктор.прототип.

  alert(p1 instanceof Person); //true
  alert(p2 instanceof Person); //true

Как вы считаете, паттерн конструктор неплох🤪

На самом деле, с паттерном конструктора еще есть некоторые проблемы ❓

Пожалуйста, продолжайте читать 👀

Проблемы с шаблоном конструктора

Метод конструктора прекрасно работает, но есть проблема с тратой памяти. Теперь мы даемPersonобъект добавляет свойствоageи методgetName, а затем сгенерируйте объект экземпляра:

  function Person(name, sex) {
  this.name = name;
  this.sex = sex;
  this.age = 20;
  this.getName = function () { console.log('name') } }
  let p1 = new Person('Jack','boy');
  let p2 = new Person('lisa','girl');
  console.log(p1)
  console.log(p2)

Вы не видели никаких проблем: 😒 На поверхности вроде бы нет проблем, но на самом деле есть большой минус. То есть для каждого объекта-экземпляра атрибут age и метод getName() имеют одинаковое содержимое.Каждый раз при генерации экземпляра он должен иметь повторяющееся содержимое и занимать больше памяти. Это не экологично и не эффективно ❎


console.log(p1.getName == p2.getName) //false

Хочешь спросить сейчас? (⊙ˍ⊙)?

Может ли свойство age и метод getName() генерироваться в памяти только один раз, и все экземпляры указывают на этот адрес памяти?

Конечно😄

Тогда смотри вниз 👇

👀👀

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

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


  function Person(name, sex) {
    this.name = name;
    this.sex = sex;
  }
  Person.prototype.age = 20;
  Person.prototype.getName = function(){
  console.log('name')
  }
  let p1 = new Person('Jack','boy');
  let p2 = new Person('lisa','girl');
  console.log(p1)
  console.log(p2)
  p1.getName()

В это время все экземплярыageи методgetNameМетод фактически представляет собой тот же адрес памяти, указывающий на объект-прототип, что повышает эффективность работы.


console.log(p1.getName == p2.getName) //true

"isPrototypeOf()"Этот метод используется для определения отношения между объектом прототипа и экземпляром.


alert(Person.prototype.isPrototypeOf(p1)); //true

alert(Person.prototype.isPrototypeOf(p2)); //true

"hasOwnProperty()"Каждый экземпляр объекта имеет метод hasOwnProperty(), который используется для определения того, является ли свойство локальным свойством или свойством, унаследованным от объекта-прототипа.


alert(p1.hasOwnProperty("name")); // true

alert(p1.hasOwnProperty("age")); // false

"в операторе"Может использоваться для определения того, содержит ли экземпляр атрибут, является ли он локальным атрибутом или нет.


alert("name" in p1); // true

alert("age" in p1); // true


//in运算符还可以用来遍历某个对象的所有属性。

or(var prop in p1) { alert("p1["+prop+"]="+p1[prop]); }

Полный пример 🎈:

function Person(name, age) {
    //私有属性和方法
    var sex = '秘密㊙';
    var getSex = function () {
        console.log(sex)
    }

    //公有属性和方法
    this.name = name;
    this.age = age;
    this.descript = '我是共有属性'
    this.getInfo = function () {
        getSex()
        console.log(this.name, this.age)
    }
}
//静态属性和方法
Person.descript = '我喜欢吃火锅...';
Person.work = function () {
    console.log('我是一名前端开发工程师')
}
//给原型对象添加属性和方法
Person.prototype.descript = '我是原型上的属性'
Person.prototype.hobby = ['游泳', '跑步'];
Person.prototype.getHobby = function () {
    console.log(p1.hobby)
}

var p1 = new Person('丽萨',23);

console.log(p1)

console.log(p1.sex) //  私有属性  undefined

console.log(p1.descript) // 我是共有属性

//因为自己有descript属性,所以直接使用自己的属性

console.log(p1.hobby)  // 原型中的属性  ["游泳", "跑步"]

console.log(Person.descript)  //静态属性  我喜欢吃火锅...

Person.work()  //静态方法    我是一名前端开发工程师

p1.getInfo() //  共有方法  秘密㊙ 丽萨  23  

p1.getHobby() //原型中的方法  打印hobby
//自己没有该方法,但是在原型上找到了,所以可以打印出来

// p1.getSex() // 私有属性   报错

// p1.work(); // 静态方法  报错

console.log(Person.sex) // 报错  静态属性


Суммировать

"1. Понятия частных атрибутов, публичных атрибутов и статических атрибутов:"

  • Частные свойства и методы: доступны только внутри конструктора и не доступны извне (свойства, объявленные с помощью var внутри конструктора);

  • Общедоступные свойства и методы (или методы экземпляра): к свойствам и методам объекта можно получить доступ вне объекта (используйте этот параметр в конструкторе или задайте его для объекта-прототипа конструктора, такого как Person.prototype.xxx);

  • Статические свойства и методы: методы, определенные в конструкторах (таких как Person.xxx), можно вызывать без экземпляра;

"2. Свойства объекта-экземпляра и свойства прототипа конструктора:"

  • Хотя свойства и методы, определенные в объекте-прототипе конструктора, не могут быть непосредственно представлены в объекте-экземпляре, объект-экземпляр может получить к ним доступ или вызвать их.

  • При обращении к свойству или методу объекта смотрит не только на объект, но и на прототип объекта, а также на прототип прототипа объекта, просматривая слой за слоем, пока не найдет свойство с совпадающим имя или метод или достигли конца цепочки прототипов (null) --(原型链查找);

"Три, три метода обхода свойств объекта экземпляра:"

  • Используйте for...in... для получения свойств самого объекта экземпляра и свойств цепочки прототипов;
  • Использование Object.keys() и Object.getOwnPropertyNames() позволяет получить только свойства самого объекта экземпляра;
  • Метод hasOwnProperty() передает имя свойства, чтобы определить, является ли свойство свойством самого экземпляра;

"В-четвертых, обратите внимание"

  • this.xxx означает добавление свойств или методов к экземпляру, созданному конструктором, а не к самому конструктору;
  • Только Person.xxx добавляет в конструктор свойства или методы;
  • Если у вас есть свойство или метод, используйте свое собственное свойство или метод, если у вас его нет, ищите его уровень за уровнем.

Упаковка после ES6

После ES6 было добавлено ключевое слово class.

Класс — это класс, который очень похож на конструктор в ES5.Большинство функций те же, однако способ написания класса может сделать функцию прототипа объекта более понятной и более соответствующей характеристикам объекта- ориентированные языки.

Отличие от метода написания пакета ES5:

"ES5 пишет:"

 function Person (name, age){
     this.name = name;
     this.age = age;
 }
 Person.prototype.getInfo = function(){
     console.log(this.name,this.age)
 }

"ES6 пишет:"

class Person{
     constructor(name, age){
        this.name = name;
        this.age = age;
     }
     getInfo(){
        console.log(this.name,this.age)
     }
 }

"разница:"

Все методы, определенные внутри класса, не являются перечисляемыми. Методы, определенные в прототипе, перечислимы.

 function Person (name, age){
     this.name = name;
     this.age = age;
 }
 Person.prototype.getInfo = function(){
     console.log(this.name,this.age)
 }

console.log( Object.keys(Person.prototype)) //["getInfo"]
class Person{
     constructor(name, age){
        this.name = name;
        this.age = age;
     }
     getInfo(){
        console.log(this.name,this.age)
     }
 }

console.log( Object.keys(Person.prototype))  //[]

"Уведомление:"

  • Constructor — это способ написать конструктор ES5, а ключевое слово this представляет объект-экземпляр. То есть конструктор Person из ES5 соответствует конструктору класса Person из ES6.
  • При определении класса нет необходимости добавлять перед ним зарезервированное слово function, и можно прямо указать определение функции.
  • Между методами не нужно ставить запятые, иначе будет сообщено об ошибке;
  • Тип данных класса — функция, сам класс указывает на конструктор
 class Person{
     constructor(name, age){
        this.name = name;
        this.age = age;
     }
 }
console.log(Person ===Person.prototype.constructor ) //true

"Все методы класса определяются в свойстве прототипа класса."

 class Person{
     constructor(name, age){
        this.name = name;
        this.age = age;
     }
     getName(){
        console.log(this.name)
     }
     getAge(){
        console.log(this.age)
     }
 }
 
//等同于

class Person{
    constructor(name, age){
       this.name = name;
       this.age = age;
    }
    
}
Person.prototype= {
    getInfo(){
        console.log(this.name,this.age)
     },
     getAge(){
        console.log(this.age)
     }
 }

hasOwnProperty()Этот метод предоставляется в javascript, чтобы определить, содержат ли собственные свойства объекта указанные свойства, и вернуть логическое значение.

class Person{
    constructor(name, age){
       this.name = name;
       this.age = age;
    }
    
}
Person.prototype= {
    getInfo(){
        console.log(this.name,this.age)
     },
     getAge(){
        console.log(this.age)
     }
 }
 var p = new Person('lisa', 23)
console.log(p.hasOwnProperty('getInfo'))  //false
console.log(p.hasOwnProperty('name'))  // true

метод конструктора

Метод конструктора — это метод класса по умолчанию, который автоматически вызывается при создании экземпляра объекта с помощью новой команды. Класс должен иметь метод конструктора, если он не определен явно, будет добавлен пустой метод конструктора.

class Person {}

//等同于

class Person {
    constructor(){}
}

"Уведомление:"

  • Метод конструктора по умолчанию возвращает объект экземпляра, то есть этот, но можно указать, что он возвращает другой объект;
  • Класс должен вызываться с new, иначе будет сообщено об ошибке.

Статические свойства и статические методы (статические)

Класс эквивалентен прототипу экземпляра, и все методы, определенные в классе, будут унаследованы экземпляром.

Но🤷

Статические свойства или статические методы относятся к свойствам или методам самого класса, а не к свойствам или методам экземпляра, поэтому класс можно вызывать напрямую.

class Person{
    constructor(name, age){
       this.name = name;
       this.age = age;
    }
    static descript = '我时一个静态属性';
    static getDescript(){
        console.log("我是一个静态方法")
    }
    
}
 console.log(Person.descript) //我时一个静态属性
 Person.getDescript() //我是一个静态方法

Сущность класса также является объектом, поэтому вы также можете использовать методы Person.xxx для определения статических свойств и статических методов.

class Person{
    constructor(name, age){
       this.name = name;
       this.age = age;
    } 
}
Person.descript = '我时一个静态属性';
Person.getDescript=function (){
    console.log("我是一个静态方法")
}

 console.log(Person.descript) //我时一个静态属性
 
 Person.getDescript() //我是一个静态方法

свойства экземпляра класса

В классе используйте=Чтобы определить свойство и метод, эффект будет таким же, как это определение, и он будет определен в экземпляре.

class Person{
    constructor(name, age){
       this.name = name;
       this.age = age;
       this.getName = function () {
           console.log(this.name)
       }
    } 
    myProp = '我是实例属性'; //实例的属性 
    getMyProp = function() { //实例的方法
        console.log(this.myProp)
    }
    getInfo(){ //属于类的原型的方法
        console.log('获取信息')
    }
}
let  p = new Person('lisa', 23)

 console.log(p.myProp) //我是实例属性
 
 p.getMyProp() //我是实例属性
 console.log(p) 
 console.log(p.hasOwnProperty('getName'))  //true
 console.log(p.hasOwnProperty('getMyProp'))  //true
 console.log(p.hasOwnProperty('getInfo'))  //false

указатель на это

Если метод класса содержит это, по умолчанию он будет указывать на экземпляр класса.

class Person{
    constructor(name, age){
       this.name = name;
       this.age = age;
       var type = '我是私有属性'
       this.desc = '我是通过this定义的属性'
       this.getName = function () {
           console.log(this.name)
       }
    } 
    desc = '我是通过等于号定义的属性'; //实例的属性 
    getMyProp = function() { 
        console.log(this) //实例对象
        console.log(this.desc)  //我是通过this定义的属性
        console.log(desc) //我是外面定义的
    }    
}

var desc = '我是外面定义的'

let  p = new Person('lisa', 23)

console.log(p)

p.getMyProp()  

"Разобрать:"

  1. Поскольку сам конструктор имеет атрибут desc, экземпляр использует этот атрибут первым. Если конструктор не имеет этого атрибута, он будет использовать этот атрибут.=определенные свойства. по умолчанию это экземпляр класса.

  2. При печати переменной desc я обнаружил, что у меня нет переменной, поэтому я искал слой за слоем, пока не нашел эту переменную в окне, а затем напечатал переменную.

Нет переменного продвижения

new Foo();

class Foo{}

В приведенном выше коде класс Foo используется первым и определяется после него, что сообщит об ошибке. Потому что ES6 не поднимает переменные в начало кода.

В ES5 есть переменное продвижение, которое можно сначала использовать, а затем определить.

var p = new Person()

function Person () {}

Суммировать

  1. Если в классе есть атрибут или метод с таким же именем, метод, определенный с помощью this, переопределит атрибут или метод, определенный с помощью =;
  2. Все методы класса определяются в свойстве прототипа класса;
  3. класс не имеет переменного повышения;
  4. Статические свойства или статические методы относятся к свойствам или методам самого класса, а не к свойствам или методам экземпляра, поэтому класс можно вызывать напрямую.
  5. Если метод класса содержит это, по умолчанию он будет указывать на экземпляр класса.

"Справочная документация:"

Я надеюсь увидеть здесь друзей и поставить мне палец вверх👍, ваша поддержка - самая большая поддержка для меня💪! ! !

В этой статье используетсяmdniceнабор текста