JavaScript. Основы прототипного наследования

Денис Завгородний

JavaScript
Основы прототипного наследования

[object Object]

	    var a = {}; // Создали пустой объект
	    // А пустой ли он?
	    console.log(a); // Object {}
	     
	    // Если проинспектировать в Chrome Dev Tools
	    // Object {}
	    //   __proto__: Object
		
  • __defineGetter__
  • __defineSetter__
  • __lookupGetter__
  • __lookupSetter__
  • constructor
  • hasOwnProperty
  • isPrototypeOf
						
  • propertyIsEnumerable
  • toLocaleString
  • toString
  • valueOf
  • get __proto__
  • set __proto__

[[Prototype]]

У объектов есть прототип

Object Человек

  • голова: 1
  • шея: 1
  • туловище: 1
  • рука: 2
  • нога: 2
 

Object Человек

  • голова: 1
  • шея: 1
  • туловище: 1
  • рука: 2
  • нога: 2

Object Василий

  • пол: мужской
  • имя: Василий
  • [[Prototype]]: Object Человек

Василий

Object Человек

  • голова: 1
  • шея: 1
  • туловище: 1
  • рука: 3
  • нога: 2
 

Василий

Василий

		    var vasiliy = {
		        gender: 'man',
		        name: 'Василий',
		        __proto__: Object Human,
		    }
		

Человек

		    var Human = {
		        head: 1,
		        neck: 1,
		        body: 1,
		        arm: 3,
		        leg: 2,
		    }
		
		    console.log(vasiliy.arm); // 3
		    Human.leg = 4;
		    console.log(vasiliy.leg); // 4
		    vasiliy.arm = 2;
		    vasiliy.leg = 2;
		    console.log(vasiliy.arm); // 2
		    console.log(vasiliy.leg); // 2
		    Human.leg = 5;
		    console.log(vasiliy.leg); // 2
		

Prototype Lookup

Василий

					    var vasiliy = {
					        gender: 'man',
					        name: 'Василий',
					        arm: 2,
					        leg: 2,
					        __proto__: Object Human,
					    }
					

Человек

					    var Human = {
					        head: 1,
					        neck: 1,
					        body: 1,
					        arm: 3,
					        leg: 2,
					    }
					
		    //Как назначить прототип?
		    vasiliy.__proto__ = Human;
		    Human.isPrototypeOf(vasiliy); //true
		    console.log(vasiliy.age); //undefined
		    Human.age = 3.2e9;
		    console.log(vasiliy.age); //3200000000
		

Не делайте так в реальных проектах

И так не делайте

		    //Массив тоже объект
		    Human.options = [];
		    console.log(vasiliy.options); //[]
		    vasiliy.options.push('smart');
		    console.log(vasiliy.options); //["smart"]
		    console.log(Human.options); //["smart"]
		    var nikolay = new Human;
		    console.log(nikolay.options); //["smart"]
		

Добавление прототипа

			Object.create(proto[, propertiesObject])
		
		    //Создать объект с прототипом
		    var obj = Object.create(null); //или var obj = {};
		    obj.value = 1;
		    var other = Object.create(obj);
		    console.log(other.value); // 1
		

ES5 и IE9+ или полифил

писать в
__proto__
плохо?

setPrototypeOf
ECMAScript 6

			Object.setPrototypeOf(obj, prototype);
		
		    //Заменить или установить прототип
		    var obj = Object.create(null);
		    obj.value = 1;
		    var other = Object.create(null);
		    console.log(other.value); // undefined
		    Object.setPrototypeOf(other, obj);
		    console.log(other.value); // 1
		

Не все можно расширить

			Object.isExtensible(obj)
		
		    /*Проверим можно ли расширить объект 
		    или сменить ему прототип */
		    Object.isExtensible(other); // true
		

В ECMAScript 6 объекты можно морозить

			Object.freeze(obj)
		
		    //Заморозим объект 
		    var freeze = Object.freeze(other);
		

Функция
конструктор

new Function()

		    function fabric() { // функция-конструктор?
		        /** Мы помним, что this магически
		        создается и связывается с созданным объектом
		        в процессе исполнения
		        т.е. сначала this = {}
		        */
		        console.log(this);
		    }
		    var obj = new fabric(); // {}
		

А что, если

		    var obj = fabric(); // ???
		    
		

Конструктор с Заглавной буквы

		    function Cart() {...}
		    var userCart = new Cart(); // Экземпляр функции
		    var userCart = new Cart; // Так, кстати, тоже можно
		

ECMAScript 6
Class

						class Human {
						  constructor() {
						    this.head = 1;
					        this.neck = 1;
					        ...
						  }
						  say() {
						    console.log(this.head);
						  }
						}
					
    					var vasiliy = new Human();
    					vasiliy = new Human();
    					vasiliy.say(); // 1
    				
			class Man extend Human {
			  constructor() {
			    super();
			    this.gender = 'man';
			    say() {
			      console.log('Im ' + this.gender);
			    }
			  }
			}
			var vasiliy = new Man();
			vasiliy.say(); // Im man
		

Подведем итоги

Спасибо!

Завгородний Денис

Найти можно в фейсбучике https://www.facebook.com/denis.zavgorodny