JavaScript: функция и объект ...? - PullRequest
41 голосов
/ 11 мая 2011

Можете ли вы вызвать функцию как объект?Например:

function Tip(txt){      
    this.content = txt;  
    this.shown = false;  
}

И:

var tip = new Tip(elem.attr('title'));

Мои вопросы:

  1. Можете ли вы вызвать new для функции, как для объекта?
  2. Использование "this" стало возможным, потому что мы используем эту функцию как объект?

Ответы [ 7 ]

120 голосов
/ 11 мая 2011

Вы ищете концепцию constructor.

Все функции в JavaScript являются объектами и могут использоваться для создания объектов:

function make_person(firstname, lastname, age) {
    person = {};
    person.firstname = firstname;
    person.lastname = lastname;
    person.age = age;
    return person;
}
make_person("Joe", "Smith", 23);
// {firstname: "Joe", lastname: "Smith", age: 23}

Однако для создания новых объектов определенного типа (то есть, которые наследуют прототип, имеют конструктор и т. Д.), Функция может ссылаться на this и , если она вызывается с помощьюnew оператор затем вернет объект со всеми атрибутами, которые определены в this в функции - this в таких случаях ссылается на новый объект, который мы создаем.

function make_person_object(firstname, lastname, age) {
    this.firstname = firstname;
    this.lastname = lastname;
    this.age = age;
    // Note, we did not include a return statement
}

Ключевое отличие, которое следует отметить между make_person и make_person_object, заключается в том, что вызов new make_person() (в отличие от простого make_person()) ничего не даст по-другому ... оба будут производить один и тот же объект.Однако, вызов make_person_object() без оператора new определит ваши атрибуты this для текущего объекта this (обычно window, если вы работаете в браузере.)

Таким образом:

var Joe = make_person_object("Joe", "Smith", 23);
console.log(Joe); // undefined
console.log(window.firstname) // "Joe" (oops)

var John = new make_person_object("John", "Smith", 45);
console.log(John); // {firstname: "John", lastname: "Smith", age: 45}

Кроме того, как указывает @RobG, этот способ работы создает ссылку на свойство prototype make_person_object для каждого «Персона», которого мы создаем.Это позволяет нам добавлять методы и атрибуты к лицам после того, как факт:

 // Assuming all that came before
make_person_object.prototype.full_name = "N/A";
make_person_object.prototype.greet = function(){ 
    console.log("Hello! I'm", this.full_name, "Call me", this.firstname); 
};
John.full_name // "N/A"
John.full_name = "John Smith"; 
make_person_object.full_name // Still "N/A"
John.greet(); // "Hello! I'm John Smith Call me John"

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

См. также:

19 голосов
/ 11 мая 2011

Каждая функция имеет ссылку на this. если вы позвоните Tip(), this будет ссылаться на глобальный объект. Если вы вызываете new Tip(), создается новый объект со ссылкой на тип Tip.prototype, и this будет ссылаться на этот новый объект.

Вы не можете использовать new на объектах, например, new {} throws TypeError: object is not a function. Если вы ссылаетесь на new Object(), то это работает, поскольку Object является функцией.

6 голосов
/ 11 мая 2011

Да. В JavaScript технически все является объектом. Когда вы используете new, он создает экземпляр объекта Tip, а затем вызывает функцию Tip, как если бы он был конструктором.

Если вы хотите добавить функции к объекту Tip, вы должны добавить их в прототип Tip следующим образом:

Tip.prototype.getContent = function() {
    return this.content;
};

Если у вас есть это, а затем вы делаете:

var tip = new Tip("this  is my content.");
alert(tip.getContent());

Будет показано сообщение «Это мой контент».

Вы можете использовать new, однако, только если объект имеет функциональную реализацию. Так что это не сработает:

var Tip = { content: txt, show: false };
var tipObj = new Tip();
3 голосов
/ 01 сентября 2017

Я пытался понять эти понятия (функции как объекты, объекты-прототипы, свойство __proto__, свойство конструктора) почти 8 лет (2008-2016).Сначала я начал работать с Дэвидом Фланаганом «JavaScript Definition Guide 5 / 6th ed» в течение 4-5 лет после многократного чтения глав 6,8,9;это не имело никакого смысла для меня, но после борьбы с Интернетом я кое-что смог управлять функциями (типичная функция C ++ со свойствами) как объектами;потому что объект также может иметь методы.И, к счастью, в 7-м году 2015 года я запустил Wrox Nicholas C. Zakas «Профессиональный JavaScript для веб-разработчиков, 3-е издание», глава 6,7;и было действительно очень полезно понять выше четыре понятия.Традиционно в C / C ++ / C # функции рассматриваются как модифицирующие объект;или, другими словами, они созданы для того, чтобы «что-то делать», поскольку объекты создаются для поддержания состояния глобального рабочего контекста с помощью методов изменения своего собственного состояния объекта.Итак, если функции могут быть объектами первого класса, то почему объекты не могут быть похожими на функции?

Главный ключевой вопрос здесь должен быть ПОЧЕМУ?Почему не один концептуальный объект, такой как «ассоциативная функция» или «цепочечные аргументы»?И вот мое понимание: Browser exe - это однопоточное приложение, которое управляет вызовом JS-интерпретатора с предопределенной цепочкой областей действия (что-то похожее на строку команд с аргументами);теперь во время выполнения движок JS (не интерпретатор) загружает код в режиме поднятия (так как нет основного метода, который поднимал бы хорошо определенные ключевые слова и его вызов).В этом поднятом коде, если функции не рассматриваются как объекты, они должны поддерживаться в отдельном контексте вызова (вне цепочки контекста), что легко возможно в c / c ++ / c # (bcoz для многопоточности и неограниченной памяти), но не в JS,Следовательно, «что-то сделать для связанного объекта» делает функцию сценария Java в качестве объекта первого класса.На самом деле объекты JS тоже делают то же самое;единственное отличие состоит в том, что «вызов объекта» не существует в объектах, где «вызов функции» представляет собой связанный контекст, который имеет смысл.Функции также можно рассматривать как «набор переменных с инструкциями на языке ассемблера с адресной связью (цепочкой)».Связывающая часть - это другая сторона истории, так как верхнее-> нижнее связывание (объект-прототип) против нижнего-> верхнее связывание (свойство __proto__) против объекта blue print-> экземпляры объекта (свойство конструктора).Несколько месяцев назад я нашел следующее изображение полезным для понимания связей.

http://judis.me/wordpress/wp-content/uploads/2015/08/JavaScriptDiagram.png "Модель объекта JS"

1 голос
/ 11 мая 2011

для # 1: существует объект с именем Function (заглавная F)

var f = new Function ("x", "y", "return x * y;");

для # 2: «это» различается в зависимости от модели инноваций (как ее называет Дуглас Крокфорд).Крокфорд сказал, что есть 4 шаблона (шаблон метода, шаблон функции, шаблон конструктора и шаблон «применения»)

1 голос
/ 11 мая 2011

Функция действует как конструктор класса.В качестве альтернативы вы можете сделать:

function Tip(txt) {
 return {
 content: txt,
 shown: false
}
}

и получить новый экземпляр с: var myTip = new Tip("my epic tip"); Это похоже, например, на c #:

public class Tip {
string text = "";
public Tip(string txt) {
text = txt;
}
}

Итак, в некотором роде.1) Вы вызываете new, так как функция по существу действует как класс, и 2) this ссылается на текущий экземпляр класса.

0 голосов
/ 09 августа 2016
  1. Фактически, все типы данных, такие как массив, функции являются объектами.
  2. Когда мы берем функцию в качестве объявления класса, это работает.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...