Обмен вопросами интервью в Дачане: как сделать значение (a===1&&a===2&&a===3) истинным?

JavaScript
Обмен вопросами интервью в Дачане: как сделать значение (a===1&&a===2&&a===3) истинным?

Когда я впервые увидел эту тему, я был просто шокирован, я проанализировал здравый смысл, который очень несовместим с нашим программированием, и подумал, что маловероятно, что переменная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Бесконечные возможности поучительны, и также рекомендуется, чтобы интервьюер не использовал такие вопросы интервью, чтобы усложнить интервьюеру~

Если статьи и заметки могут немного помочь вам или вдохновить, пожалуйста, не скупитесь на лайки и подборки, они должны быть для меня самой большой мотивацией двигаться дальше 😁

Прикрепите ссылку к заметке, читайте больше качественных статей в прошлом, можете переходить к просмотру, если вам понравилось, можете поставить палец вверх и поощрить: