Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Создание объекта в Javascript (https://javascript.ru/forum/misc/81698-sozdanie-obekta-v-javascript.html)

denis_alekss 14.01.2021 22:20

Создание объекта в Javascript
 
Не вызывается почему то конструктор, пишет что не определенный конструктор хотя я ему определяю список аргументов при вызове.

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>Тест</title>
 </head>
 <body>  
<p id="result"></p>

    <script>
let Person = {
	constructor:function(name,age,gender){
		this.name = name;
		this.age = age;
		this.gender = gender;
		return this;
	},
	greet: function(){
	   console.log("My name is " + this.name);
	}
};

var tom = new Person.constructor("Вася",18,"female");
tom.greet();
 </script>
 </body>
</html>


Почему я не могу использовать просто new для создания объекта, а обязательно нужно использовать Object.create.. Почему нельзя обойтись просто new для вызова конструктора?

voraa 15.01.2021 07:17

Надо так

let Person =function(name,age,gender){
        this.name = name;
        this.age = age;
        this.gender = gender;
        return this;
    };
Person.prototype.greet= function(){
       console.log("My name is " + this.name);
    };
var tom = new Person("Вася",18,"female");
tom.greet();


Либо так
class Person {
    constructor (name,age,gender){
        this.name = name;
        this.age = age;
        this.gender = gender;
        return this;
    }
    greet (){
       console.log("My name is " + this.name);
    }
}

var tom = new Person("Вася",18,"female");
tom.greet();


В крайнем случае (непонятно, зачем) так
let Person = {
    constructor:function(name,age,gender){
        this.name = name;
        this.age = age;
        this.gender = gender;
       this.greet = Person.greet;
        return this;
    },
    greet: function(){
       console.log("My name is " + this.name);
    }
};
 
var tom = new Person.constructor("Вася",18,"female");
tom.greet();

denis_alekss 15.01.2021 21:48

Разницы нет что с return this (я так понимаю это ссылка на объект класса)
Если убрать return this, без него также работает код, причем одинаково.

Почему во втором console.log не происходит вывод 18? Ведь я передал через конструктор аргумент 18.
Здесь решил попробовать наследование.

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>Тест</title>
 </head>
 <body>  
<p id="result"></p>

    <script>
let Person =function(name,age,gender){
        this.name = name;
        this.age = age;
        this.gender = gender;
    //    return this;
    };
Person.prototype.greet= function(){
       console.log("My name is " + this.name);
    };



let Son = function(age,skils){
this.skils = skils || [];
Person.apply(this,arguments)
}


Son.prototype = Object.create(Person.prototype);
Son.prototype.constructor = Son;
let a = new Person("Петя",25,"female");
let b = new Son(18,["рисует","поет","водит"]);
console.log(a.age);
console.log(b.age + b.skils);
 </script>
 </body>
</html>

voraa 15.01.2021 23:48

let Person =function(name,age,gender){ // какие параметры?

let Son = function(age,skils)
Person.apply(this,arguments) // А что вы передаете?

Alexandroppolus 16.01.2021 15:58

Цитата:

Сообщение от denis_alekss
Разницы нет что с return this (я так понимаю это ссылка на объект класса)
Если убрать return this, без него также работает код, причем одинаково.

https://learn.javascript.ru/construc...ruktora-return

denis_alekss 17.01.2021 23:52

Вот еще вариант один:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <script>
        let Person = function Pers(name, age, gender) { // Имя будет Pers
            this.name = name;
            this.age = age;
            this.gender = gender;
        };
        Person.prototype.greet = function () {
            console.log("My name is " + this.name);
        }
 
        let Person2 = Person;
        Person2.prototype.goodbye = function () {
            console.log("Goodbye, " + this.name);
        }
 
        let Son = function (age, skils) { // Имя будет Son
            // Родительский конструктор вызывается до дочернего конструктора,
            // чтобы не было перезаписывания новых полей.
            Person.call(this, undefined, age, undefined);
            this.skils = skils || [];
			this.gender;
        }
 
        let Sunny = Son;
        Sunny.prototype = Object.create(Person.prototype);
        Sunny.prototype.constructor = Sunny; // Имя будет Son
 
        let a = new Person("Петя", 25, "female");
        console.log(a);
        console.log(a.constructor.name);
 
        let b = new Son(18, ["рисует", "поет", "водит"]);
        console.log(b);
		console.log(b.name);
    </script>
</body>
</html>


Задался еще таким вопросом. Я передал аргументы конструктору Person создав объект а,
let a = new Person("Петя", 25, "female");


а как получить эти значения объекту b и вывести?

Если написать так: console.log(b.name); получим undefined при выводе, а мне к примеру нужно унаследовать от родителя эти значения name, age, gender и вывести через потомка.

voraa 18.01.2021 09:54

Цитата:

Сообщение от denis_alekss
        let Person2 = Person;
        Person2.prototype.goodbye = function () {
            console.log("Goodbye, " + this.name);
        }

Это зачем?
Новой функции не будет.
Функция останется одна. Только две переменные будут на нее ссылаться.
И Person2.prototype это тоже самое, что Person.prototype. Один и тот же объект.
Цитата:

Сообщение от denis_alekss
а как получить эти значения объекту b и вывести?

Никак. Это разные объекты.
При создании объекта b вы не передали ему значения для name и gender. Потому, что при создании объектов Son вы не предусматриваете эти параметры, а для Person передаете undefined.
Вы хотите, что бы b был как то связан с а? Брал е поля?
Но если вы напишите

let a = new Person("Петя", 25, "male");
let a1 = new Person("Вася", 14, "male");
let a2 = new Person("Маша", 25, "female");

let b = new Son(18, ["рисует", "поет", "водит"]);

То с каким из a, a1, a2 по вашему должен быть связан b?

Son должен быть таким
let Son = function (name, age, skils) { // Имя будет Son
            Person.call(this, name, age, 'male');
            this.skils = skils || [];
            this.gender;    // А это что и зачем?
        }

denis_alekss 18.01.2021 23:42

Придумал как сделать.
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <script>
        let Person = function Pers(name, age, gender) { // Имя будет Pers
            this.name = name;
            this.age = age;
            this.gender = gender;
        };
        Person.prototype.greet = function () {
            console.log("My name is " + this.name);
        }
 
        let Person2 = Person;
        Person2.prototype.goodbye = function () {
            console.log("Goodbye, " + this.name);
        }
 
        let Son = function (name,age,gender,skils) { // Имя будет Son
            // Родительский конструктор вызывается до дочернего конструктора,
            // чтобы не было перезаписывания новых полей.
            Person.call(this, name, age, gender);
            this.skils = skils || [];
        }
 
        let Sunny = Son;
        Sunny.prototype = Object.create(Person.prototype);
        Sunny.prototype.constructor = Sunny; // Имя будет Son
 
        let a = new Person("Петя", 25, "female");
        console.log(a);
        console.log(a.constructor.name);
 
        let b = new Son(a.name,a.age,a.gender, ["рисует", "поет", "водит"]);
		
        console.log(b);
		console.log(b.name);
    </script>
</body>
</html>


Просто засунул объект а созданный от Person в сына в качестве аргументов.

let b = new Son(a.name,a.age,a.gender, ["рисует", "поет", "водит"]);


Я просто хотел понять как наследовать потомку свойства и значения полученные конструктором родителя, добавляя в потомке еще свои свойства, расширяя класс родителя.

voraa 19.01.2021 10:11

Цитата:

Сообщение от denis_alekss
как наследовать потомку свойства и значения полученные конструктором родителя

Здесь нет никакого наследования. Просто два разных объекта, у которых некоторые свойства совпадают.
Наследование предполагает, что если изменяется "родительское своиство", то оно изменяется и у самого объекта.

denis_alekss 25.01.2021 22:41

Скажите, а в чем разница?

Sunny.prototype = Object.create(Person.prototype);


от

Sunny.prototype = Person.prototype;


Оба варианта работают одинаково при выводе

Внимательно перечитал вроде как и вот через консоль решил поиграться с деревом, что на что ссылается.
Объект можно создать так:

[PHPHTML]
Teacher.prototype = Object.create( Person.prototype );

Teacher.prototype = new Person();

Teacher.prototype = { __proto__: Person.prototype };

Object.setPrototypeOf(Teacher.prototype, Person.prototype);

class Teacher extends Person {};
[/PHPHTML]

Вроде как все объявления работают одинаково как я понял, не важно как объявишь.
Правильно я понимаю картину?Возьмем этот код:
function Person(name) {
    this.name = name
}
 
Person.prototype.output = function(){
    console.log(this.name)
}
 
function Teacher(name, skill) {
    Person.apply(this, [name])
    this.skill = skill
}
 
Teacher.prototype = Object.create(Person.prototype)
 
Teacher.prototype.constructor = Teacher
 
Teacher.prototype.output = function(){
    console.log(this.name, this.skill)
}
 
var t = new Teacher("john", "super man")
 
console.log(t.constructor.name)
 
t.output();


Когда мы объявили функцию любую у него автоматом создался prototype, скрытое свойство, зарезервированное самим движком JS. В данном коде когда мы написали function Teacher просто в коде, автоматом в скрытом свойстве [[prototype]] движка JS появилось Teacher.prototype. Когда я создал объект t
t.__proto__ == Teacher.prototype


Далее ссылка на родителя идет тоже через прото
Teacher.prototype.__proto__ == Person.prototype

А дальше
Person.prototype.__proto__ == Object.prototype

И далее
Object.prototype.__proto__ == null

И на этом конец?


Часовой пояс GMT +3, время: 14:26.