Когда я впервые увидел эту тему, я был просто шокирован, я проанализировал здравый смысл, который очень несовместим с нашим программированием, и подумал, что маловероятно, что переменнаяa
Быть равным трем значениям 1, 2 и 3 одновременно в одной и той же ситуации, это фантазия, не меньшая, чем Гольдбах1+1=1
Это предположение, но все возможно.Из любопытства, после долгих размышлений, я решил попробовать решение.
Моя идея пришла из другого похожего вопроса интервью, с которым я столкнулся ранее:
// 设置一个函数输出一下的值
f(1) = 1;
f(1)(2) = 3;
f(1)(2)(3) = 6;
В то время решением было использоватьtoString
илиvalueOf
Понял, тогда давайте пересмотримtoString
иvalueOf
метод, так что мы можем получить более глубокое понимание этого типа проблемы:
Например, у нас есть объект, который не переопределяетtoString()
Методы иvalueOf()
В случае метода вывод результата в узле или браузере выглядит следующим образом.
class Person {
constructor() {
this.name = name;
}
}
const best = new Person("Kobe");
console.log(best); // log: Person {name: "Kobe"}
console.log(best.toString()); // log: [object Object]
console.log(best.valueOf()); // log: Person {name: "Kobe"}
console.log(best + "GiGi"); // log: [object Object]GiGi
best | Person |
best.toString() | [object Object] |
best.valueOf() | Person |
best + 'GiGi' | [object Object]GiGi |
Из приведенного выше вывода мы можем наблюдать деталь,toString()
вывод[object Object]
,иvalueOf()
выводPerson
сам объект, и когда операция поbest + 'GiGi'
Это оказалось выходом, когда[object Object]GiGi
, мы можем изначально сделать вывод, что объект называетсяtoString()
Вычисляется строка, полученная методом, является ли она оператором+
Магия этого?
Чтобы проверить наш вывод из предыдущего шага, мы делаем небольшое изменение и ставимvalueOf
Метод переопределяется один раз:
class Person {
constructor(name) {
this.name = name;
}
// 复写 valueOf 方法
valueOf() {
return this.name;
}
}
best | Person |
best.toString() | [object Object] |
best.valueOf() | Person |
best + 'GiGi' | KobeGiGi |
На этот раз есть только один результат, отличный от приведенного выше, и это последнийbest + 'GiGi'
Два результата до и после копируютсяvalueOf()
Метод после этого изменился, из чего видно, что суть объекта принципиально не изменилась, но при использовании его как прямой операции его значение копируется изvalueOf()
получены в и продолжают участвовать в последующих операциях.
Конечно, не забывайте, что у нас есть еще одинtoString()
метод, поэтому мы также перезаписываем его, чтобы увидеть, не повлияет ли это на результат:
class Person {
constructor(name) {
this.name = name;
}
valueOf() {
return this.name;
}
toString() {
return `Bye ${this.name}`;
}
}
best | Person |
best.toString() | Bye Kobe |
best.valueOf() | Kobe |
best + 'GiGi' | KobeGiGi |
мы обнаруживаемbest + 'GiGi'
По-прежнему ничего не изменилось, все еще используется наша последняя перезаписьvalueOf()
результат
На самом деле мы переписываемvalueOf
метод, не обязательно называемыйvalueOf()
Возвращаемое значение вычисляется. ноvalueOf
Если возвращаемое значение является базовым типом данных, оно будет рассчитано в соответствии с этим значением.Если это не базовый тип данных, оно будет использоватьtoString()
Значение, возвращаемое методом, вычисляется.
class Person {
constructor(name) {
this.name = name;
}
valueOf() {
return this.name;
}
toString() {
return `Bye ${this.name}`;
}
}
const best = new Person({ name: "Kobe" });
console.log(best); // log: Person name: {name: "Kobe"}
console.log(best.toString()); // log: Bye [object Object]
console.log(best.valueOf()); // log: Person {name: "Kobe"}
console.log(best + "GiGi"); // log: [object Object]GiGi
best | Person |
best.toString() | Bye [object Object] |
best.valueOf() | {name: "Kobe"} |
best + 'GiGi' | Bye [object Object]GiGi |
Глядя на приведенный выше пример, теперь входящийname
является объектомnew Person({ name: "Kobe" })
, не является примитивным типом данных, поэтому при выполнении операции сложения беритеtoString()
Значение, возвращаемое методом, вычисляется, конечно, если нетvalueOf()
метод будет выполнятьсяtoString()
метод.
Итак, после того, как мы так долго закладывали основу, мы собираемся раскрыть ответ, используя приведенные выше принципы, чтобы ответить на этот вопрос:
class A {
constructor(value) {
this.value = value;
}
toString() {
return this.value++;
}
}
const a = new A(1);
if (a == 1 && a == 2 && a == 3) {
console.log("Hi Eno!");
}
Здесь проще, просто перепишите прямоtoString()
метод, так как нетvalueOf()
, когда он выносит оперативное решениеa == 1
будет выполнен, когдаtoString()
результат.
class A {
constructor(value) {
this.value = value;
}
valueOf() {
return this.value++;
}
}
const a = new A(1);
if (a == 1 && a == 2 && a == 3) {
console.log("Hi Eno!");
}
Конечно, вы также можете не использоватьtoString
, заменяетсяvalueOf
Кроме того, эффект тот же:
class A {
constructor(value) {
this.value = value;
}
valueOf() {
return this.value++;
}
}
const a = new A(1);
console.log(a);
if (a == 1 && a == 2 && a == 3) {
console.log("Hi Eno!");
}
Поэтому, когда объект выполняет операции (такие как сложение, вычитание, умножение и деление, оценка равенства), часто возникаютvalueOf()
илиtoString
Проблема вызова этого объекта обычно скрывает функцию за переменной.
Конечно, принцип следующей задачи на самом деле такой же, с прилагаемым решением:
// 设置一个函数输出一下的值
f(1) = 1;
f(1)(2) = 3;
f(1)(2)(3) = 6;
function f() {
let args = [...arguments];
let add = function() {
args.push(...arguments);
return add;
};
add.toString = function() {
return args.reduce((a, b) => {
return a + b;
});
};
return add;
}
console.log(f(1)(2)(3)); // 6
Конечно, это еще не конец, здесь будут какие-то специальные решения, на самом деле, при использовании объектов, если объект является массивом, то приведенная выше логика все еще будет верна, но в этот разtoString()
становится неявным вызовомjoin()
метод, другими словами, если объект является массивом, когда вы не переопределяете другиеtoString()
метод, реализация которого по умолчанию заключается в вызове массиваjoin()
возвращаемое значение метода какtoString()
Возвращаемое значение , значит, есть новое решение этой проблемы, то есть без перезаписиtoString()
под предлогом перезаписиjoin()
метод, превратить его вshift()
метод, который удаляет из него первый элемент массива и возвращает значение первого элемента.
class A extends Array {
join = this.shift;
}
const a = new A(1, 2, 3);
if (a == 1 && a == 2 && a == 3) {
console.log("Hi Eno!");
}
Наши поиски еще не окончены, внимательные студенты обнаружат, что наша тема如何让(a===1&&a===2&&a===3)的值为 true
, но все вышеперечисленное касается свободного равенства==
В случае строгого равенства===
будет ли приведенный выше результат другим?
Ответ другой, вы можете попробовать изменить приведенные выше свободные условия на строгую отладку и попробовать еще раз, чтобы узнать результат.
class A extends Array {
join = this.shift;
}
const a = new A(1, 2, 3);
// == 改成 === 后:
if (a === 1 && a === 2 && a === 3) {
console.log("Hi Eno!"); // Hi Eno!此时再也没出现过了
}
Так как же решить ситуацию в это время? Мы можем рассмотреть возможность использованияObject.defineProperty
решить это, потому чтоVue
И известный метод теперь также является общеизвестным в интервью, и мы можем использовать его для захватаa
переменная, пусть она автоматически увеличивается, когда мы получаем ее значение, тогда проблема может быть решена:
var value = 1;
Object.defineProperty(window, "a", {
get() {
return this.value++;
}
});
if (a === 1 && a === 2 && a === 3) {
console.log("Hi Eno!");
}
Наверху мы захватываем мирwindow
вышеa
,когдаa
Запускается каждый раз, когда выносится решениеget
Атрибут получает значение, и каждый раз, когда значение будет получено, будет запущена функция для выполнения автоинкремента, и если он оценивается три раза, он будет автоматически инкрементироваться три раза, поэтому формула будет установлена в конец.
Конечно, есть и другие методы, вот еще один пример, например, использование скрытых символов, чтобы скрыть интервьюера:
var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if (aᅠ == 1 && a == 2 && ᅠa == 3) {
console.log("Hi Eno!");
}
Приведенное выше решение очень запутанно. Если вы не будете осторожны, вы подумаете, что это три одинаковыхa
, по сути, это по сути определение трех разныхa
ценность,a
Перед и после есть скрытые символы, поэтому при отладке скопируйте и вставьте приведенный выше код для отладки,Chrome
При попадании рукой можно использовать специальные средства, чтобы сделатьa
Поставьте одну-две красные точки сзади, и когда вы сядете в машину, инструмент отладки скроет эти следы, чтобы скрыть небо и показать интервьюеру, который какое-то время не отвечал.
Наконец, я желаю вам всем найти хорошую работу в новом году.Приведенный выше код в основном не используется в реальных ситуациях, но он используется для изученияJS
Бесконечные возможности поучительны, и также рекомендуется, чтобы интервьюер не использовал такие вопросы интервью, чтобы усложнить интервьюеру~
Если статьи и заметки могут немного помочь вам или вдохновить, пожалуйста, не скупитесь на лайки и подборки, они должны быть для меня самой большой мотивацией двигаться дальше 😁
Прикрепите ссылку к заметке, читайте больше качественных статей в прошлом, можете переходить к просмотру, если вам понравилось, можете поставить палец вверх и поощрить: