Статьи

Основы объектно-ориентированного JavaScript

В последние годы все большую популярность приобретает JavaScript, отчасти благодаря библиотекам, разработанным для облегчения создания приложений / эффектов JavaScript для тех, кто еще не полностью освоил основной язык.

В то время как в прошлом был распространенный аргумент, что JavaScript был базовым языком и был очень «шлепком» без реального основания; это уже не так, особенно с введением крупномасштабных веб-приложений и «адаптаций», таких как JSON (JavaScript Object Notation).

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

1
2
3
function myObject(){
    
   };

Поздравляю, вы только что создали объект. Существует два способа создания объекта JavaScript: это «Функции конструктора» и «Литеральная запись». Выше приведена функция Constructor, я вскоре объясню, в чем разница, но прежде чем я это сделаю, вот как выглядит определение объекта с использованием буквенной нотации.

1
2
3
var myObject = {
    
   };

Литерал является предпочтительным вариантом для разделения имен, чтобы ваш код JavaScript не мешал (или наоборот) другим сценариям, выполняющимся на странице, а также, если вы используете этот объект как один объект и не требует более одного экземпляра object, тогда как нотация типа функции Constructor предпочтительна, если вам нужно выполнить некоторую начальную работу перед созданием объекта или требовать несколько экземпляров объекта, где каждый экземпляр может быть изменен в течение времени существования сценария. Давайте продолжим строить оба наших объекта одновременно, чтобы мы могли наблюдать, в чем различия.

1
2
3
4
5
6
function myObject(){
       this.iAm = ‘an object’;
       this.whatAmI = function(){
           alert(‘I am ‘ + this.iAm);
       };
   };
1
2
3
4
5
6
var myObject = {
       iAm : ‘an object’,
       whatAmI : function(){
           alert(‘I am ‘ + this.iAm);
       }
   }

Для каждого из объектов мы создали свойство «iAm», которое содержит строковое значение, которое используется в методе наших объектов «whatAmI», который предупреждает сообщение.

Свойства — это переменные, созданные внутри объекта, а методы — это функции, созданные внутри объекта.

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

Чтобы использовать свойство, сначала вы вводите объект, к которому оно принадлежит — в данном случае это myObject — а затем для ссылки на его внутренние свойства ставите точку и затем имя свойства, чтобы оно в конечном итоге выглядело как myObject.iAm ( это вернет «объект»).

Для методов это то же самое, за исключением того, что для выполнения метода, как и для любой функции, вы должны поставить круглые скобки после нее; в противном случае вы просто будете возвращать ссылку на функцию, а не то, что на самом деле возвращает функция. Так что это будет выглядеть как myObject.whatAmI () (это предупредит «Я — объект»).

  • Объект конструктора имеет свои свойства и методы, определенные с ключевым словом «this» перед ним, тогда как в буквальной версии — нет.
  • В объекте конструктора свойства / методы имеют свои «значения», определенные после знака равенства «=», тогда как в буквальной версии они определяются после двоеточия «:».
  • Функция конструктора может иметь (необязательно) точки с запятой ‘;’ в конце каждого объявления свойства / метода, тогда как в буквальной версии, если у вас есть более одного свойства или метода, они ДОЛЖНЫ быть разделены запятой ‘,’, и они НЕ МОГУТ иметь точку с запятой после них, иначе JavaScript вернет ошибка.

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

Чтобы использовать объект с буквенной нотацией, вы просто используете его, ссылаясь на имя переменной, поэтому везде, где это требуется, вы вызываете его, набирая;

1
myObject.whatAmI();

С помощью функций конструктора вы должны сначала создать (создать новый экземпляр) объект; Вы делаете это, печатая;

1
2
var myNewObject = new myObject();
   myNewObject.whatAmI();

Давайте использовать нашу предыдущую функцию конструктора и основываться на ней, чтобы она выполняла некоторые базовые (но динамические) операции, когда мы ее создаем.

1
2
3
4
5
6
function myObject(){
       this.iAm = ‘an object’;
       this.whatAmI = function(){
           alert(‘I am ‘ + this.iAm);
       };
   };

Как и любая функция JavaScript, мы можем использовать аргументы с нашей функцией конструктора;

1
2
3
4
5
6
function myObject(what){
    this.iAm = what;
    this.whatAmI = function(language){
        alert(‘I am ‘ + this.iAm + ‘ of the ‘ + language + ‘ language’);
    };
};

Теперь давайте создадим экземпляр нашего объекта и вызовем его метод whatAmI, заполнив обязательные поля, как мы это делаем.

1
2
var myNewObject = new myObject(‘an object’);
   myNewObject.whatAmI(‘JavaScript’);

Появится предупреждение «Я являюсь объектом языка JavaScript».

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

Сначала мы создадим литерал Object;

01
02
03
04
05
06
07
08
09
10
11
12
var myObjectLiteral = {
       myProperty : ‘this is a property’
   }
    
   //alert current myProperty
   alert(myObjectLiteral.myProperty);
    
   //change myProperty
   myObjectLiteral.myProperty = ‘this is a new property’;
    
   //alert current myProperty
   alert(myObjectLiteral.myProperty);

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
var myObjectLiteral = {
       myProperty : ‘this is a property’
   }
    
   //alert current myProperty
   alert(myObjectLiteral.myProperty);
    
   //define new variable with object as value
   var sameObject = myObjectLiteral;
    
   //change myProperty
   myObjectLiteral.myProperty = ‘this is a new property’;
    
   //alert current myProperty
   alert(sameObject.myProperty);

Теперь давайте попробуем аналогичное упражнение с функцией конструктора.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
//this is one other way of creating a Constructor function
   var myObjectConstructor = function(){
       this.myProperty = ‘this is a property’
   }
    
   //instantiate our Constructor
   var constructorOne = new myObjectConstructor();
    
   //instantiate a second instance of our Constructor
   var constructorTwo = new myObjectConstructor();
    
   //alert current myProperty of constructorOne instance
   alert(constructorOne.myProperty);
     
    //alert current myProperty of constructorTwo instance
   alert(constructorTwo.myProperty);

Как и ожидалось, оба возвращают правильное значение, но давайте изменим myProperty для одного из экземпляров.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//this is one other way of creating a Constructor function
   var myObjectConstructor = function(){
       this.myProperty = ‘this is a property’
   }
    
   //instantiate our Constructor
   var constructorOne = new myObjectConstructor();
    
   //change myProperty of the first instance
   constructorOne.myProperty = ‘this is a new property’;
    
   //instantiate a second instance of our Constructor
   var constructorTwo = new myObjectConstructor();
    
   //alert current myProperty of constructorOne instance
   alert(constructorOne.myProperty);
     
    //alert current myProperty of constructorTwo instance
   alert(constructorTwo.myProperty);

Как вы можете видеть из этого примера, даже если мы изменили свойство constructorOne, оно не повлияло на myObjectConstructor и, следовательно, не повлияло на constructorTwo. Даже если экземпляр constructorTwo был создан до того, как мы изменили свойство myProperty для constructorOne, это все равно не повлияло бы на свойство myProperty для constructorTwo, поскольку это совершенно другой экземпляр объекта в памяти JavaScript.

Так какой из них вы должны использовать? Ну, это зависит от ситуации, если вам нужен только один объект такого типа для вашего скрипта (как вы увидите в нашем примере в конце этой статьи), тогда используйте литерал объекта, но если вам нужно несколько экземпляров объекта где каждый экземпляр не зависит от другого и может иметь разные свойства или методы в зависимости от способа его конструирования, тогда используйте функцию конструктора.

При объяснении функций конструктора было выброшено много ключевых слов «this», и я подумал, в какое время лучше поговорить о области действия!

Теперь вы можете спросить: «Что это за область, о которой вы говорите?» Область действия в JavaScript основана на функции / объекте, поэтому это означает, что если вы находитесь за пределами функции, вы не можете использовать переменную, определенную внутри функции (если вы не используете замыкание).

Однако существует цепочка областей действия, которая означает, что функция внутри другой функции может обращаться к переменной, определенной в ее родительской функции. Давайте посмотрим на пример кода.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<script type=»text/javascript»>
 
var var1 = ‘this is global and is available to everyone’;
 
function function1(){
 
    var var2 = ‘this is only available inside function1 and function2’;
     
    function function2(){
     
        var var3 = ‘this is only available inside function2’;
     
    }
     
}
 
</script>

Как вы можете видеть в этом примере, var1 определен в глобальном объекте и доступен для всех функций и объектов, var2 определен внутри function1 и доступен для function1 и function2, но если вы попытаетесь ссылаться на него из глобального объекта, он будет выдает ошибку ‘var2 is undefined’, var3 доступен только для function2.

Так что же означает «это»? В браузере «this» ссылается на объект окна, поэтому технически окно — это наш глобальный объект. Если мы находимся внутри объекта, ‘this’ будет ссылаться на сам объект, однако если вы находитесь внутри функции, это все равно будет ссылаться на объект окна, а также, если вы находитесь внутри метода, который находится внутри объекта, ‘ это будет относиться к объекту.

Благодаря нашей цепочке областей действия, если мы находимся внутри подобъекта (объекта внутри объекта), «this» будет ссылаться на подобъект, а не на родительский объект.

В качестве примечания также стоит добавить, что при использовании таких функций, как setInterval, setTimeout и eval, когда вы выполняете функцию или метод с помощью одного из них, «this» ссылается на объект окна, так как это методы окна, поэтому setInterval ( ) и window.setInterval () совпадают.

Хорошо, теперь, когда у нас это есть, давайте сделаем пример из реального мира и создадим объект проверки формы!

Сначала я должен познакомить вас с функцией addEvent, которую мы создадим. Она представляет собой комбинацию функции addEventListener () ECMAScript (Firefox, Safari и т. Д.) И функции attachEvent () сценария Microsoft ActiveX.

1
2
3
4
5
6
7
8
9
function addEvent(to, type, fn){
       if(document.addEventListener){
           to.addEventListener(type, fn, false);
       } else if(document.attachEvent){
           to.attachEvent(‘on’+type, fn);
       } else {
           to[‘on’+type] = fn;
       }
   };

Это создаст новую функцию с тремя аргументами: объект DOM, to которому мы присоединяем событие, type — тип события, а fn — функция, запускаемая при запуске события. Сначала он проверяет, поддерживается ли addEventListener, если это так, он будет использовать это, если нет, он будет проверять наличие attachEvent и, если все остальное не поможет, вы, вероятно, используете IE5 или что-то такое же устаревшее, поэтому мы добавим событие непосредственно в его свойство события (примечание: третья опция перезапишет любую существующую функцию, которая могла быть присоединена к свойству события, тогда как первые две добавят ее как дополнительную функцию к свойству события).

Теперь давайте настроим наш документ так, чтобы он был похож на то, что вы могли видеть при разработке jQuery.

В jQuery вы бы имели;

1
2
3
$(document).ready(function(){
       //all our code that runs after the page is ready goes here
   });

Используя нашу функцию addEvent мы имеем;

1
2
3
addEvent(window, ‘load’, function(){
       //all our code that runs after the page is ready goes here
   });

Теперь для нашего объекта Form.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
var Form = {
 
    validClass : ‘valid’,
     
    fname : {
        minLength : 1,
        maxLength : 15,
        fieldName : ‘First Name’
    },
     
    lname : {
        minLength : 1,
        maxLength : 25,
        fieldName : ‘Last Name’
    },
     
     
    validateLength : function(formEl, type){
        if(formEl.value.length > type.maxLength || formEl.value.length < type.minLength ){
            formEl.className = formEl.className.replace(‘ ‘+Form.validClass, »);
            return false;
        } else {
            if(formEl.className.indexOf(‘ ‘+Form.validClass) == -1)
            formEl.className += ‘ ‘+Form.validClass;
            return true;
        }
    },
     
     
    validateEmail : function(formEl){
        var regEx = /^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/;
        var emailTest = regEx.test(formEl.value);
        if (emailTest) {
            if(formEl.className.indexOf(‘ ‘+Form.validClass) == -1)
            formEl.className += ‘ ‘+Form.validClass;
            return true;
        } else {
            formEl.className = formEl.className.replace(‘ ‘+Form.validClass, »);
            return false;
        }
    },
     
    getSubmit : function(formID){
        var inputs = document.getElementById(formID).getElementsByTagName(‘input’);
        for(var i = 0; i < inputs.length; i++){
            if(inputs[i].type == ‘submit’){
                return inputs[i];
            }
        }
        return false;
    }
         
};

Так что это довольно просто, но может быть легко расширено.

Чтобы разбить это сначала, мы создаем новое свойство, которое является просто строковым именем нашего «действительного» класса CSS, который при применении к полю формы добавляет допустимые эффекты, такие как зеленая рамка. Мы также определяем два наших lname , fname и lname , поэтому мы можем определить их собственные свойства, которые могут использоваться методами в другом месте, это minLength минимальное количество символов, которое могут иметь эти поля, maxLength максимальное количество символов поле может иметь и fieldName которое на самом деле не используется, но может быть использовано для идентификации поля с помощью удобной для пользователя строки в сообщении об ошибке (например, «Поле имени необходимо».).

Затем мы создаем метод validateLength, который принимает два аргумента: formEl элемент DOM и type который ссылается на один из используемых подобъектов (т. Е. Fname или lname). Эта функция проверяет, находится ли длина поля между диапазонами minLength и maxLength, если это не так, мы удаляем наш действительный класс (если он существует) из элемента и возвращаем false, в противном случае, если это так, мы добавляем действительный класс и возвращаем правда.

Затем у нас есть метод validateEmail, который принимает элемент DOM в качестве аргумента, затем мы проверяем это значение элементов DOM по регулярному выражению типа электронной почты; снова, если он проходит, мы добавляем наш класс и возвращаем true и наоборот.

Наконец, у нас есть метод getSubmit. Этот метод получает идентификатор формы, а затем перебирает все входные элементы внутри указанной формы, чтобы найти, какой из них имеет тип submit (type = «submit»). Причина этого метода — вернуть кнопку отправки, чтобы мы могли отключить ее, пока форма не будет готова к отправке.

Давайте поместим этот объект валидатора для работы в реальной форме. Сначала нам нужен наш HTML.

01
02
03
04
05
06
07
08
09
10
<body>
    
   <form id=»ourForm»>
       <label>First Name</label><input type=»text» /><br />
       <label>Last Name</label><input type=»text» /><br />
       <label>Email</label><input type=»text» /><br />
       <input type=»submit» value=»submit» />
   </form>
    
   </body>

Теперь давайте получим доступ к этим входным объектам с помощью JavaScript и проверим их при отправке формы.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
addEvent(window, ‘load’, function(){
     
     
    var ourForm = document.getElementById(‘ourForm’);
    var submit_button = Form.getSubmit(‘ourForm’);
    submit_button.disabled = ‘disabled’;
     
    function checkForm(){
        var inputs = ourForm.getElementsByTagName(‘input’);
        if(Form.validateLength(inputs[0], Form.fname)){
            if(Form.validateLength(inputs[1], Form.lname)){
                if(Form.validateEmail(inputs[2])){
                      
                        submit_button.disabled = false;
                        return true;
                                         
                }
            }
        }
             
        submit_button.disabled = ‘disabled’;
        return false;
         
    };
     
    checkForm();
    addEvent(ourForm, ‘keyup’, checkForm);
    addEvent(ourForm, ‘submit’, checkForm);
       
     
});

Давайте разберем этот код.

Мы оборачиваем наш код в функцию addEvent, чтобы при загрузке окна запускался этот скрипт. Сначала мы берем нашу форму, используя ее ID, и помещаем ее в переменную с именем ourForm , затем мы берем нашу кнопку отправки (используя наш метод формы getSubmit объектов) и помещаем ее в переменную с именем submit_button , а затем устанавливаем для отключенного атрибута кнопок отправки значение ‘ отключен’.

Далее мы определяем функцию checkForm. При этом все входные данные внутри поля формы сохраняются в виде массива, и мы присоединяем его к переменной с именем .. как вы уже догадались .. inputs ! Затем он определяет некоторые вложенные операторы if, которые проверяют каждое из полей внутри массива входных данных на соответствие нашим методам Form. По этой причине мы вернули истину или ложь в наших методах, поэтому, если она возвращает истину, мы передаем оператор if и продолжаем переходить к следующему, но если она возвращает ложь, мы выходим из операторов if.

Следуя нашему определению функции, мы выполняем функцию checkForm при начальной загрузке страницы, а также присоединяем функцию к событию keyup и к событию submit.

Вы можете спросить, зачем прикреплять, чтобы отправить, если мы отключили кнопку отправки. Хорошо, если вы сфокусировались на поле ввода и нажали клавишу ввода, он попытается отправить форму, и нам нужно проверить это, поэтому наша функция checkForm возвращает true (отправляет форму) или false (не отправляет) форма).

Итак, мы узнали, как определять различные типы объектов в JavaScript и создавать свойства и методы в них. Мы также изучили изящную функцию addEvent и получили возможность использовать наш объект в базовом примере из реального мира.

На этом завершаются основы объектной ориентации JavaScript. Надеемся, что это может начать вас на пути к созданию собственной библиотеки JavaScript! Если вам понравилась эта статья и вас интересуют другие темы, связанные с JavaScript, опубликуйте их в комментариях, так как я с удовольствием продолжу их писать. Спасибо за прочтение.

Почему бы также не проверить диапазон элементов JavaScript на CodeCanyon. Вы можете найти скрипты для создания слайдеров , обратного отсчета , загрузчиков и загрузчиков и многое другое.

Популярные элементы JavaScript на Envato Market
Популярные элементы JavaScript на Envato Market