Отличные ответы выше. Я хочу только добавить, что внутри области вашей функции вы можете присвоить значение этой переменной переменной let self = this;
, а затем внутри обратного вызова просто обратиться к данным типа self.data
.
Ваш код :
function MyConstructor(data, transport) {
this.data = data;
let self = this; //ADD THIS LINE
transport.on('data', function () {
alert(self.data); //USE IT LIKE THIS
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
Когда выражение ==
используется для выражения типа object
, оно будет разрешено System.Object.ReferenceEquals
.
Equals
является всего лишь методом virtual
и ведет себя как таковой, поэтому будет использоваться переопределенная версия (которая для типа string
сравнивает содержимое).
Я бы добавил, что если вы нарисуете свой объект на строку, то он будет работать правильно. Вот почему компилятор даст вам предупреждение:
Возможное непреднамеренное сравнение ссылок; чтобы получить сравнение значений, введите левую сторону для ввода «string»
blockquote>
object expr = XXX; if (expr == "Energy") { ... }
, то, поскольку левая сторона имеет тип времени компиляции object
, компилятор должен использовать перегрузку operator ==(object, object)
. Он проверяет ссылочное равенство. Невозможно предсказать, будет ли это дано true
или false
из-за интернирования строк . Если вы знаете i>, левая сторона либо null
, либо тип string
, перед использованием ==
отдайте левую сторону в string
.
– Jeppe Stig Nielsen
13 February 2014 в 11:46
При сравнении ссылки объекта на строку (даже если ссылка на объект ссылается на строку), особое поведение оператора ==
, специфичного для класса строк, игнорируется.
Обычно (когда не имея дело со строками, то есть), Equals
сравнивает значения, а ==
сравнивает ссылки на объекты. Если два объекта, которые вы сравниваете, ссылаются на один и тот же точный экземпляр объекта, то оба будут возвращать true, но если один имеет тот же контент и поступает из другого источника (это отдельный экземпляр с теми же данными), то только Equals будут return true. Однако, как отмечено в комментариях, строка является особым случаем, потому что она переопределяет оператор ==
, так что при использовании чисто ссылок на строки (а не ссылок на объекты) сравниваются только значения, даже если они являются отдельными экземплярами. Следующий код иллюстрирует тонкие различия в поведении:
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
Выход:
True True True
False True True
False False True
Во-первых, есть разность. Для чисел
> 2 == 2.0
True
> 2.Equals(2.0)
False
И для строк
> string x = null;
> x == null
True
> x.Equals(null)
NullReferenceException
В обоих случаях ==
ведет себя более полезно, чем .Equals
==
является хорошим. Например, должно ли 16777216.0f равно (int) 16777217, (double) 16777217.0, обоих или ни одного? Сравнение между интегральными типами является точным, но сравнение с плавающей запятой должно выполняться только ИМХО со значениями, которые явно передаются в соответствующие типы. Сравнение a float
с чем-то другим, кроме float
или double
с чем-то другим, кроме double
, поражает меня как основного запаха кода, который не следует компилировать без диагностики.
– supercat
16 August 2013 в 21:20
x == y
не подразумевает x/3 == y/3
(попробуйте x = 5
и y = 5.0
).
– Colonel Panic
19 August 2013 в 09:24
/
для целочисленного деления является дефектом в дизайне C # и Java. Паскаль div
и даже VB.NET ` are much better. The problems with
== `хуже, хотя: x==y
и y==z
не подразумевают, что x==z
(рассмотрим три числа в моем предыдущем комментарии). Что касается отношения, которое вы предлагаете, даже если x
и y
оба float
или оба double
, x.equals((Object)y)
не означает, что 1.0f/x ==
1.0f / y` (если бы у меня были мои барабанщики, это гарантировало бы это, даже если ==
не различает положительные и нулевые значения Equals
).
– supercat
23 August 2013 в 22:20
Когда мы создаем какой-либо объект, в объекте есть две части, одна из которых является контентом, а другая - ссылкой на этот контент. ==
сравнивает как контент, так и ссылку; equals()
сравнивает только контент
http://www.codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals- and-Eq
a
и b
являются строковыми ссылками, то результат a == b
не зависит от того, ссылаются ли ссылки на один и тот же объект.
– phoog
8 January 2015 в 17:39
Поскольку статическая версия метода .Equal
не упоминалась до сих пор, я хотел бы добавить это здесь, чтобы суммировать и сравнить 3 варианта.
MyString.Equals("Somestring")) //Method 1
MyString == "Somestring" //Method 2
String.Equals("Somestring", MyString); //Method 3 (static String.Equals method) - better
, где MyString
переменная, которая приходит откуда-то еще в коде.
Фоновая информация и summerize:
В Java, использующем ==
для сравнения строк, не следует использовать. Я упоминаю об этом, если вам нужно использовать оба языка, а также сообщить, что с помощью ==
можно также заменить что-то лучше на C #.
В C # нет никакой практической разницы для сравнения строк с использованием метода 1 или метода 2, если оба имеют строку типа. Однако, если один из них является нулевым, один имеет другой тип (например, целое число) или один представляет объект, который имеет другую ссылку, то, как показывает первоначальный вопрос, может возникнуть впечатление, что сравнение содержимого для равенства может не вернуть вы ожидаете.
Предлагаемое решение:
Поскольку использование ==
не совсем совпадает с использованием .Equals
при сравнении вещей, вы можете использовать статические String.Equals . Таким образом, если обе стороны не являются одним и тем же типом, вы все равно будете сравнивать контент, а если он будет нулевым, вы избежите исключения.
bool areEqual = String.Equals("Somestring", MyString);
Это немного больше, чтобы писать, но в мое мнение, безопаснее использовать.
Вот некоторая информация, скопированная из Microsoft:
public static bool Equals (string a, string b);
Параметры
a
String
Первая строка для сравнения или null
.
b
String
Вторая строка для сравнения или null
.
Возвращает Boolean
true
, если значение a
совпадает с значением b
; в противном случае false
. Если оба a
и b
равны null
, метод возвращает true
.
==
и .Equals
зависят от поведения, определенного в фактическом типе и фактическом типе на сайте вызова. Оба являются просто методами / операторами, которые могут быть переопределены на любом типе и заданы любым поведением, которое автор так желает. По моему опыту, я считаю, что люди обычно реализуют .Equals
на объекте, но пренебрегают имплементацией оператора ==
. Это означает, что .Equals
будет фактически измерять равенство значений, а ==
будет измерять, являются ли они одной и той же ссылкой.
Когда я работаю с новым типом, определение которого в потоке или написанием общих алгоритмов, я считаю, что наилучшей практикой является следующий
Object.ReferenceEquals
напрямую (не требуется в общем случае) EqualityComparer<T>.Default
. В некоторых случаях, когда Я чувствую, что использование ==
неоднозначно. Я явно использую Object.Reference
в коде для удаления двусмысленности.
Эрик Липперт недавно сделал сообщение в блоге по вопросу о том, почему существует 2 метода равенство в CLR. Это стоит прочитать
== Оператор 1. Если операнды Типы значений и их значения равны, он возвращает true else false. 2. Если операнды Reference Types , за исключением строки, и оба относятся к одному и тому же объекту, он возвращает true else false. 3. Если операнды являются строковыми типами, а их значения равны, он возвращает true else false.
.Equals 1. Если операнды являются ссылочными типами, он выполняет Reference Equality , который есть, если оба относятся к одному и тому же объекту, он возвращает true else false. 2. Если Операнды являются типами значений, то в отличие от оператора ==, он сначала проверяет их тип, и если их типы одинаковы, он выполняет == operator else, он возвращает false.
==
может быть перегружен для любого типа, а не только для строки. Описывая исключительное исключение только для строки, искажает семантику оператора. Было бы более точным, хотя, возможно, и не очень полезным, сказать «если операнды являются ссылочными типами, он возвращает true, если операнды относятся к одному и тому же объекту, если не существует применимой перегрузки, и в этом случае реализация этой перегрузки определяет результат & Quot ;. То же самое верно для Equals
с добавленным усложнением, что это виртуальный метод, поэтому его поведение можно переопределить, а также перегрузить.
– phoog
8 January 2015 в 17:35
Существует еще одно измерение для более раннего ответа от @BlueMonkMN. Дополнительное измерение состоит в том, что ответ на вопрос о названии @ Drahcir, как указано, также зависит от , как мы пришли к значению string
. Для иллюстрации:
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("\n Case1 - A method changes the value:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
Console.WriteLine("\n Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));
Выход:
True True True
Case1 - A method changes the value:
False True True
False False True
Case2 - Having only literals allows to arrive at a literal:
True True True
True True True
Насколько я понимаю, ответ прост:
Надеюсь, я прав и ответил на ваш вопрос.
Действительно большие ответы и примеры!
Я хотел бы просто добавить фундаментальное различие между двумя,
. Операторы, такие как
blockquote>==
, не являются полиморфными, аEquals
isС учетом этой концепции, если вы выработаете какой-либо пример (просмотрев ссылочный тип левой руки и правой руки и проверив / зная, действительно ли тип имеет == оператор перегружен и Equals override), вы обязательно получите правильный ответ.
Я немного смущен. Если тип содержимого времени выполнения имеет строку типа, то оба == и Equals должны возвращать значение true. Однако, поскольку это не так, тогда тип времени выполнения не является строкой, а вызов Equals на нем выполняет ссылочное равенство, и это объясняет, почему Equals («Energy Attack») терпит неудачу. Однако во втором случае решение о том, какой перегруженный == статический оператор следует вызывать, выполняется во время компиляции, и это решение выглядит как (строка, строка). это говорит мне, что Content обеспечивает неявное преобразование в строку.
==
Оператор == может использоваться для сравнения двух переменных любого типа и просто сравнивает биты.
int a = 3;
byte b = 3;
if (a == b) { // true }
Примечание: в левой части int больше нолей, но здесь нас здесь не интересует.
int a (00000011) == byte b (00000011)
Помните, что оператор-оператор заботится только о шаблоне бит в переменной.
Использовать == Если две ссылки (примитивы) относятся к одному и тому же объекту в куче.
Правила то же, является ли переменная ссылкой или примитивной.
Foo a = new Foo();
Foo b = new Foo();
Foo c = a;
if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }
a == c истинно a == b является ложным
, битовая диаграмма одинакова для a и c, поэтому они равны с использованием ==.
Equal ():
Используйте метод equals (), чтобы увидеть, равны ли два разных объекта.
Такие, как два разных объекта String, которые оба представляют символы в «Jane»
object a = 3; object b = 3; Console.WriteLine(a == b);
. Выходной сигнал является ложным, хотя битовые шаблоны значений одинаковы. Также важны типы операндов. Причина, по которой нам «не волнует», о различном количестве нулей в вашем примере является то, что к тому времени, когда мы вызываем оператор equals, число нулей фактически такое же i>, из-за неявного преобразования.
– phoog
8 January 2015 в 18:11
Добавление еще одной точки в ответ.
.EqualsTo()
метод дает вам возможность сравнивать с культурой и чувствительностью к регистру.
Маркер ==
в C # используется для двух разных операторов проверки равенства. Когда компилятор встречает этот токен, он проверяет, осуществил ли какой-либо из сравниваемых типов перегрузку оператора равенства или для сравнения отдельных типов комбинации (*), или для комбинации типов, к которым могут быть преобразованы оба типа. Если компилятор найдет такую перегрузку, он будет использовать его. В противном случае, если оба типа являются ссылочными типами, и они не являются несвязанными классами (либо они могут быть интерфейсом, либо они могут быть связанными классами), компилятор будет рассматривать ==
как оператор сравнения ссылок. Если ни одно из условий не применяется, компиляция не будет выполнена.
Обратите внимание, что некоторые другие языки используют отдельные токены для двух операторов проверки равенства. Например, в VB.NET токен =
используется в выражениях исключительно для перегружаемого оператора проверки равенства, а Is
используется в качестве оператора эталонного теста или нулевого теста. An использовать =
для типа, который не переопределяет оператор проверки равенства, не будет работать, как будет пытаться использовать Is
для любых целей, кроме проверки ссылочного равенства или недействительности.
(*) Типы обычно только перегружают равенство для сравнения с самим собой, но может быть полезно, чтобы типы перегружали оператор равенства для сравнения с другими конкретными типами; например, int
мог бы (и IMHO должен был иметь, но не сделал) определил операторы равенства для сравнения с float
, так что 16777217 не сообщил бы себя равным 16777216f. Как бы то ни было, поскольку такой оператор не определен, C # будет продвигать int
до float
, округляя его до 16777216f, прежде чем оператор проверки равенства увидит его; этот оператор затем видит два равных числа с плавающей запятой и сообщает о них как о равных, не подозревая о округлении, которое имело место.
3
как равные 3.0f
. Если мы требуем, чтобы программист сказал, что предназначено в каждом случае, тогда нет опасности поведения по умолчанию, приводящего к непреднамеренным результатам, поскольку поведение по умолчанию отсутствует.
– phoog
8 January 2015 в 18:27
Единственное различие между Equal и == заключается в сравнении типов объектов. в других случаях, таких как ссылочные типы и типы значений, они почти одинаковы (либо оба являются поразрядным равенством, либо оба являются ссылочным равенством).
object: Equals: bit-wise равенство ==: reference равенство
string: (equals и == одинаковы для строки, но если одна из строк была изменена на объект, тогда результат сравнения будет разным). Равны: побитовое равенство ==: битовое равенство
Подробнее см. здесь .
object
(обратите внимание на моноширинный шрифт) технически означает «выражение типаSystem.Object
». Это не имеет никакого отношения к типу времени выполнения экземпляра, на который ссылается выражение. Я думаю, что оператор «определяемые пользователем» обрабатываются какvirtual
методы ». крайне вводит в заблуждение. Они обрабатываются как перегруженные методы и зависят только от типа экземпляров в режиме компиляции. Фактически, после вычисления набора определяемых пользователем операторов, остальная процедура связывания будет в точности методом алгоритма перегрузки метода – Mehrdad Afshari 16 July 2012 в 23:28virtual
зависит от фактического типа времени выполнения экземпляра, тогда как это полностью i> игнорируется при разрешении перегрузки оператора, и это действительно весь смысл моего ответа. – Mehrdad Afshari 17 July 2012 в 18:22