Проблема здесь в том, что hasOwnProperty()
— это метод объекта, и вся его функция заключается в работе со свойствами этого объекта. Таким образом, он работает только в том случае, если при его вызове ему задан правильный контекст объекта. Обычно это письменные методы, ожидающие, что контекст объекта должен получить значение this
при вызове метода.
В большинстве случаев в JavaScript (за исключением функций, определенных с помощью стрелочного синтаксиса) значение this
определяется тем, как вызывается метод. Обычный и наиболее распространенный способ вызвать метод для соответствующего объекта:
obj.method()
Это приведет к тому, что JavaScript установит this
в obj
при вызове method()
.
Если вы сделаете что-то вроде этого:
var myFunction = obj.method;
И затем вы вызываете этот метод без ссылки на объект, как в:
var myFunction = obj.method;
myFunction();
Тогда ссылка на объект в obj
теряется и никак не передается методу. Интерпретатор JavaScript выберет значение по умолчанию для this
.
В строгом режиме this
будет установлено на undefined
, и любой метод, который попытается использовать это значение, ожидая, что это ссылка на объект, потерпит неудачу.
В нестрогом режиме браузер установит this
так, чтобы он указывал на некоторое значение по умолчанию. В браузере это объект window
. Итак, если бы вы попытались использовать этот метод для объекта окна, о чудо, он бы сработал. Я считаю это своего рода случайностью, а не хорошим кодом.
ИМО, мораль этой истории заключается в том, что любой метод, который должен быть связан с объектом, должен вызываться с явной ссылкой на объект. Затем это устраняет всю путаницу, устраняет все различия между строгим и нестрогим режимами и устраняет все различия между браузером и Node.js.
Итак, почему это происходит:
имеет собственное свойство (x)
TypeError: невозможно преобразовать undefined или null в объект
Если вы пытаетесь вызвать hasOwnProperty()
для проверки свойства глобального объекта в node.js, вызовите метод с контекстом объекта global
, как показано ниже:
global.hasOwnProperty("a")
Это будет работать везде и считается хорошим и правильным кодом Javascript. Вызов его без надлежащего контекста объекта приводит к тому, что значение this
устанавливается на значение по умолчанию. В node.js это значение по умолчанию не обязательно будет глобальным объектом. Но во всех случаях вы НИКОГДА не должны полагаться на то, каким будет это значение по умолчанию. Программируйте правильно, всегда указывая нужную ссылку на объект, и ваш код везде будет работать нормально.
К вашему сведению, есть больше способов контролировать, что this
передается функции, чем просто obj.method()
. Вы можете прочитать о других способах здесь, в этом другом ответе а>. Они включают в себя такие вещи, как .call()
, .apply()
, стрелочные функции (в ES6 а>) и т. д.
person
jfriend00
schedule
05.01.2017
hasOwnProperty()
, к которой можно получить доступ без какого-либо префикса, поэтому вам не следует его использовать. Если вы описываете проблему, которую на самом деле пытаетесь решить, мы можем лучше объяснить, как вы должны кодировать ее. - person jfriend00   schedule 05.01.2017hasOwnProperty
. - person Yerko Palma   schedule 05.01.2017Object.prototype.hasOwnProperty()
, который также будет доступен в объектеglobal
в node.js, поскольку он является производным от Object. Я не знаю об отдельной версии (называемой без префикса), которая входит в какой-либо стандарт. Можете ли вы указать на какой-либо стандартный документ по этому поводу? - person jfriend00   schedule 06.01.2017window
вместоglobal
). Наверняка существует существует спецификация, отображающая, как свойства глобального объекта становятся доступными в виде переменных верхнего уровня, верно? И тот, который указывает, наследуется ли глобальный объект отObject.prototype
и каким образом? Я не удивлюсь, если Node не имеет такой спецификации, но WebIDL может иметь ее для браузера, если ее нет в ECMAScript. (@jfriend00) - person apsillers   schedule 06.01.2017hasOwnProperty
. - person Yerko Palma   schedule 06.01.2017Object.prototype.hasOwnProperty.call(null, 'x')
, что может означать только то, что его прямой вызов приводит к тому, чтоthis
будет чем-то другим, а не глобальным объектом (что вы обычно ожидаете от напрямую вызываемых функций). В спецификации не упоминается, как определяетсяthis
. ecma-international.org/ecma-262/6.0 / но я могу ошибаться. - person Joseph   schedule 06.01.2017global
, используйтеglobal.hasOwnProperty()
. Работает как чемпион. Проблема решена. Если вы пытаетесь сделать что-то еще, кроме проверки наличия свойства у глобального объекта, опишите эту проблему, чтобы мы могли посоветовать другое решение. Вызов метода без ссылки на объект, как вobj.method()
, или использование.call()
или.apply()
вызывает проблемы и, вероятно, вызывает проблемы сthis
при выполненииhasOwnProperty()
. Но, честно говоря, меня не очень интересует почему, потому что это неправильный способ кодирования. - person jfriend00   schedule 06.01.2017this
определяется семантикой времени выполнения выражения вызова функции: ecma-international.org/ecma-262/6.0/#sec-function-call - person apsillers   schedule 06.01.2017window.hasOwnProperty
иhasOwnProperty
). Многие пишутalert()
, например, вместоwindow.alert()
и это не вызывает комментариев типа стандартного определения нет... - просто работает. Но есть разница в node.js. И, возможно, вы правы - возможно, это какой-то странный побочный эффект. Я просто хотел знать ... если это недостаточно важно для этого сайта, я мог бы спросить где-нибудь еще. Спасибо, в любом случае! - person Alexander Mihailov   schedule 06.01.2017alert()
— это просто глобальная функция. Это не метод, выполняющий операцию над объектом, к которому он присоединен.hasOwnProperty()
— это метод, который необходимо вызывать в контексте определенного объекта, поскольку он работает с этим объектом. Если вы попытаетесь позвонитьObject.prototype.hasOwnProperty("foo")
, это тоже не сработает. n Должно бытьObject.prototype.hasOwnProperty.call(someObj, "foo")
илиsomeObj.hasOwnProperty("foo")
. То же самое сglobal
. - person jfriend00   schedule 06.01.2017window
. ссылка 2) как бы вы прокомментировали это, особенно раздел под названием Простой вызов б> - person Alexander Mihailov   schedule 06.01.2017window
. Вот как работает глобальная область видимости. На самом деле, я думаю (неправильное) понимание того, как работает глобальная область видимости, лежит в основе вашего замешательства. (Тем не менее, у меня есть небольшое идеологическое несогласие с jfriend00; я думаю, что это хороший вопрос и возможность узнать о некоторых низкоуровневых поведениях, определенных ECMAScript.) - person apsillers   schedule 06.01.2017hasOwnProperty
не является также методом объекта окна? а так еще и глобальная функция (по Вашей логике?) - person Alexander Mihailov   schedule 06.01.2017hasOwnProperty
глобально доступен из всех областей, и это так, потому что это свойство существует вwindow
(путем наследованияObject.prototype
). Его можно вызвать, потому что это функция, но это не означает, что он имеет разумный результат, когда вызывается как голыйhasOwnProperty()
, конечно, как уже объяснял jfriend00. - person apsillers   schedule 06.01.2017hasOwnProperty
сопоставляется непосредственно с глобальной областью (window
). В node.js это не так. Почему ? (Я имею в виду здесь: код отлично работает в браузере, если вы заменитеglobal
наwindow
) - person Alexander Mihailov   schedule 06.01.2017hasOwnProperty()
, для выполнения своей работы требуется значениеthis
, и это значениеthis
должно быть объектом, над которым вы пытаетесь работать. Таким образом, вызовhasOwnProperty("foo")
работает только в том случае, если значение по умолчаниюthis
при вызове функции оказывается таким, каким вам нужно. В строгом режиме этого НИКОГДА не будет, потому чтоthis
будетundefined
. В нестрогом режиме вам может повезти. Но общий смысл заключается в том, что метод, который работает с объектом, ДОЛЖЕН вызываться в контексте ЭТОГО конкретного объекта, иначе он не сможет правильно выполнять свою работу. - person jfriend00   schedule 06.01.2017alert()
не работает с объектом, поэтому его можно вызвать в любом случае, черт возьми, и он будет работать нормально.hasOwnProperty()
должен вызываться в контексте конкретного объекта (если только вы не надеетесь, что система волшебным образом установит правильноеthis
по умолчанию, что никогда не будет истинным в строгом режиме и никогда не должно использоваться в хорошем программировании на Javascript). Вы понимаете, чтоhasOwnProperty()
— это метод объекта, и при вызове ему должна быть предоставлена ссылка на объект для работы? Это ключ здесь. - person jfriend00   schedule 06.01.2017hasOwnProperty()
, как метод узнает, над каким объектом работать? Есть миллионы потенциальных объектов. Как он узнает, на каком из них вы просите посмотреть недвижимость? Если вы не полагаетесь на назначение нестрогого режимаthis
объектуwindow
в браузере (что является плохим поведением при кодировании), это никогда не сработает. Методы, работающие с объектом, должны вызываться с контекстом объекта, с которым вы хотите, чтобы они работали, иначе они не смогут выполнять свою работу должным образом. - person jfriend00   schedule 06.01.2017this
в вызове функции. По сути, вы спрашиваете, почему неправильный код работает в некоторых средах. IMO, обучение здесь заключается в том, как писать правильный код, который работает во всех средах, а не в том, чтобы подробно разобраться, почему он работает в некоторых средах. - person jfriend00   schedule 06.01.2017alert()
является глобальным. Просто так получилось, что в среде браузера (в основном по плохим историческим причинам) все глобальные переменные до ES6 являются свойствами объектаwindow
. В ES6 глобальный объект, объявленный с помощьюconst
илиlet
, НЕ находится в объектеwindow
, поскольку Javascript/браузеры пытаются исправить плохое поведение (глобальные объекты, объявленные с помощьюvar
, все еще находятся в объектеwindow
в ES6 для обратной совместимости). node.js не имеет такого же плохого поведения с глобальными переменными, и отчасти это связано с тем, что вы никогда не сможете запустить какой-либо код в истинном глобальном пространстве имен, поскольку весь код выполняется в контексте модуля. - person jfriend00   schedule 06.01.2017this
разрешается в случае простого вызова и точно так же работает в Mozilla FF. Они говорят, что поскольку следующий код не находится в строгом режиме и поскольку значение this не установлено вызовом, по умолчанию будет использоваться глобальный объект:. Так что кажется, что в строгом режиме вызов по умолчанию не к глобальному объекту, а кnull
(илиundefined
, я не знаю). И в этот момент я кое-что узнал, и я думаю, что это ответ. Спасибо, сэр! - person Alexander Mihailov   schedule 06.01.2017this
, это ПЛОХОЙ код. Не делай этого. Немедленно измените весь свой код на строгий режим. - person jfriend00   schedule 06.01.2017