👣👣 Три основные особенности 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()
"Разобрать:"
-
Поскольку сам конструктор имеет атрибут desc, экземпляр использует этот атрибут первым. Если конструктор не имеет этого атрибута, он будет использовать этот атрибут.
=
определенные свойства. по умолчанию это экземпляр класса. -
При печати переменной desc я обнаружил, что у меня нет переменной, поэтому я искал слой за слоем, пока не нашел эту переменную в окне, а затем напечатал переменную.
Нет переменного продвижения
new Foo();
class Foo{}
В приведенном выше коде класс Foo используется первым и определяется после него, что сообщит об ошибке. Потому что ES6 не поднимает переменные в начало кода.
В ES5 есть переменное продвижение, которое можно сначала использовать, а затем определить.
var p = new Person()
function Person () {}
Суммировать
- Если в классе есть атрибут или метод с таким же именем, метод, определенный с помощью this, переопределит атрибут или метод, определенный с помощью =;
- Все методы класса определяются в свойстве прототипа класса;
- класс не имеет переменного повышения;
- Статические свойства или статические методы относятся к свойствам или методам самого класса, а не к свойствам или методам экземпляра, поэтому класс можно вызывать напрямую.
- Если метод класса содержит это, по умолчанию он будет указывать на экземпляр класса.
"Справочная документация:"
Я надеюсь увидеть здесь друзей и поставить мне палец вверх👍, ваша поддержка - самая большая поддержка для меня💪! ! !
В этой статье используетсяmdniceнабор текста