Промежуточный и продвинутый интерфейс? Вы действительно понимаете эти унарные операторы?

внешний интерфейс JavaScript
Промежуточный и продвинутый интерфейс? Вы действительно понимаете эти унарные операторы?

Это 27-й день моего участия в августовском испытании обновлений. Узнайте подробности события:Испытание августовского обновления.

предисловие

Унарный оператор не очень бросается в глаза, но имеет большой эффект, пожалуйста, не игнорируйте его! Подойди к ней и влюбись в нее!

определение

Операторы, требующие только одного операнда, называются унарными операторами.

Или код легко понять:

+1 // 一个操作数

1 + 2 // 两个操作数

Список унарных операторов

оператор инструкция
delete удалить свойство объекта
void Вычисляет данное выражение и возвращает значение undefined
typeof Возвращает базовый тип данных
+ Преобразование операции в числовой тип
- Преобразование операции в числовой тип и отрицание
~ побитовый оператор НЕ
! Логический оператор НЕ

delete

Основные инструкции

Оператор удаления используется для удаления свойства объекта.
Истинно для всех случаев, если только свойство не является ненастраиваемым собственным свойством.
при этих обстоятельствах,

  • Возвращает false для нестрогого режима.
  • В строгом режиме, если свойство является свойством, которое само по себе не настраивается, будет выдано исключение TypeError.

Что такое ненастраиваемое свойство, посмотрите на фрагмент кода, чтобы знать:

var Employee = {};
Object.defineProperty(Employee, 'name', { 
    configurable: false
});

console.log(delete Employee.name);  // returns false

пройти черезObject.definePropertyнастраиватьconfigurable: false

Меры предосторожности

Помимо многих атрибутов, которые нельзя удалить, следует отметить следующее:

  1. delete не может удалить свойства прототипа

  2. Когда вы удаляете элемент массива, длина массива не изменяется.

  3. Метод удаления может разрушить форму объекта, что также приведет к тому, что V8 регенерирует новый скрытый класс для объекта., что приводит к снижению производительности.

    Дополнительные сведения о проблемах с производительностью удаления см.Почему серия: не используйте удаление, если в этом нет необходимости

  4. В строгом режиме будет выдана синтаксическая ошибка (SyntaxError), если операция удаления используется для прямой ссылки на переменную, параметр функции или имя функции.

function func(param) {
  // SyntaxError in strict mode.
  console.log(delete param); // false
}

реальный бой

Мы можем не столкнуться с использованиемdeleteместо действия.
Мы временно добавляем к объекту какие-то временные методы или значения промежуточного состояния, выполняем какие-то операции со столбцами, а затем удаляем эти свойства.

Приходите к классическому делу, рукописномуcall:

// 不考虑node环境, 不考虑严格模式, 不考虑被freeze
Function.prototype.call = function (context){
    if (typeof this !== 'function') {
        throw new TypeError('not a funciton')
    }    
    var argsArr = [];
    for(var i = 1; i< arguments.length; i++){
        argsArr.push("arguments[" + i + "]");
    }    
    var  context  = context == null ? window : Object(context);   
    // 保留现场
    var hasFn =  ("__fn__" in context); // 不推荐做法
    var originFn;
    if(hasFn){
       originFn = context.__fn__;
    }; 
    
    context.__fn__ =  this;
    
    var code = "context.__fn__(" +  argsArr.join(",")  +  ")";
    var result = eval(code);

    if(hasFn){
        context.__fn__ = originFn
    }else {
        delete context.__fn__;
    }
    return result;    
}

мы кладемcontextсвойства__fn__Чтобы указать на текущую функцию, после завершения выполнения, в зависимости от того, есть ли до__fn__свойства, чтобы решить, является лиdeleteили восстановить исходное значение.

void

Основные инструкции

оператор void Вычисляет заданное выражение и возвращает значение undefined.

сцены, которые будут использоваться

Старые версии некоторых браузеров undefined могут быть перезаписаны, см. рисунок:
Вот как я эмулирую IE8 с IE11

image.png

Так, так в этом случаеvoid 0Сравниватьundefinedнадежный.voidЭта унарная операция, за исключением этого, готовится вернутьundefinedКроме того, есть два других распространенных применения:

  1. href тега ничего не делает
    <a href="javascript:void(0);">

  2. IIFE выполняется немедленно

;void function(msg){
    console.log(msg)
}("你好啊");

Конечно, более прямой путь:

;(function(msg){
    console.log(msg)
})("你好啊");

С появлением стрелочных функций появилось новое применение:Избегайте утечек в стрелочных функциях

button.onclick = () => void doSomething();

typeof

Оператор возвращает строку, представляющую тип неоцененного операнда.

Базовые типы данных до ES5 читали все.typeof null === "object" Естественно, эта ветка само собой разумеется.
Symbol(новое в ECMAScript 2015) также частый гость,BigIntНе должно быть незнакомым.

typeof BigInt(10) // bigint
typeof Symbol.for("key") // symbol

Временная мертвая зона

Добавлена ​​область действия блокаletиconstПосле этого использование typeof для переменных let и const в блоках до их объявления вызывает ошибку ReferenceError. мы называем егоВременная мертвая зона

typeof newLetVariable; // ReferenceError
typeof newConstVariable; // ReferenceError
typeof newClass; // ReferenceError

let newLetVariable;
const newConstVariable = 'hello';
class newClass{};

специальныйdocument.all

typeof document.all === 'undefined'; // true

document.allВозвращает все элементы страницы, стоит сказать, что это не стандартный API.
Продукт эпохи IE4, он даже используется как способ определить, является ли он браузером IE.

if(document.all){
    //is IE
}

Это чувствуют и другие производители браузеров.document.allПолезно, но вы не хотите нарушать работу существующего веб-сайта. Итак, document.all возвращает все элементы, ноtypeofЗначениеundefined, разве это не смешно.

Даже не изменился на IE10:

image.png

IE11 завершил это состояние:

image.png

Как определить тип данных

  1. typeof
    Определите примитивные и ссылочные типы данных.
  2. instanceof
    Определите ссылочные типы и обоснование запроса цепочки прототипов.
  3. constructor
    Определите ссылочный тип, но это недопустимо, конструктор можно переписать, второй вариант.
  4. Object.prototype.toString
    Определите примитивные и ссылочные типы данных.
  5. определение типа утки
    Посмотрим, сколько еженедельных загрузок достигнет800 Вт is-promiseисходный код библиотеки
function isPromise(obj) {
  return !!obj && (typeof obj === 'object' || typeof obj === 'function') 
  && typeof obj.then === 'function';
}

Конечно, комбинированный эффект лучше.

+и-

Начнем с интересного вопроса: Найдите окончательный результат вывода.

var a = b = 1;
console.log(+a++ + + +b++)  // 2  等同于 +a + + +b  == a + b

var a = b = 1;
console.log(++a+ + + ++b)  // 4   等同于 (++a)+ + + (++b) ==  a + b

var a = b = 1;
console.log(-a-- + - -b--) // 0   等同于 -a + - -b = -a + b

Унарный оператор + преобразует свой операнд в числовой тип.

Тип параметра результат
Undefined NaN
Null +0
Boolean true возвращает 1, иначе возвращает 0
String Пустая строка становится 0, и если появляется какой-либо недопустимый числовой символ, результатом будет NaN
Number Нет преобразования, вернуть исходное значение
Symbol TypeError
BigInt TypeError
Object toPrimitive=>valueOf=>toString=>Number()
  1. Сначала вызовите метод объекта Symbol.toPrimitive, если этот метод не существует.
  2. Затем вызовите valueOf объекта, чтобы получить исходное значение, если полученное значение не является исходным значением.
  3. Затем вызовите toString объекта, чтобы превратить его в строку.
  4. Наконец, преобразуйте строку в число на основе метода Number().

Подробнее о конвертации Unary + Operator

Один юань-и+Очень похоже, но в конце наоборот.

~

Меняет местами биты своего операнда, что может быть не совсем понятно. Дайте формулу и вы поймете

~x = -(x + 1)

Он также удаляет десятичные знаки, удаляется,не закругленный

~2.3  // -3
~2.6  // -3

пример~5 = -(5+1) = -6

console.log(~5);// -6

отрицать

Затем мы можем написать функцию инверсии на основе этого:

function reveNumber (val: number) {
  return ~val + 1
}

Вывод:

~val + 1 = -(val + 1) + 1 = -val - 1 + 1  = -val

Целочисленный бит

Я уверен, что многие люди использовали это

function getIntPart(val: number){
    return ~~val;
}

toInt(3.4)  // 3

Вывод:
Потому что ~ потеряет десятичную часть, бросая туда-сюда дважды, остается только целая часть.

 ~~val = ~(-(val + 1))  = -(-(val + 1) + 1) = -(-val -1 + 1) = val

Дополнительные замечания:
из-за цифрового~-1и~4294967295(232-1) использует 32-битное представление, и оба результата равны 0.

!

Отрицается, возвращает логическое значение.

Возвращает true для следующих случаев, false для остальных:

  • null
  • NaN
  • 0
  • "" or '' or ``
  • undefined

Двойной нон (!!)

дваОператор явно приводит любое значение к соответствующему логическому значению.

!!({}) // true

мы часто любим использовать!и!!Суждение о правильном и неправильном на самом деле не является строгим, и этот пункт необходимо прояснить, поэтому лучше добавить некоторые предварительные суждения или четко знать тип данных.

запутанные цифры

мы можем передать некоторыеСимволы генерируют цифры и буквы, полезный для запутывания, например:

+[]  // 0
+!+[] // 1 
+!+[]+!+[] // 2
(![]+[])[+!![]] // a

Разве это не интересно?Основная идея - преобразование типов + индексация массива

напиши в конце

Если вы считаете, что это хорошо, ваши лайки и комментарии — самая большая мотивация для меня двигаться вперед.

Пожалуйста, посетите группу технического обменаПодойди сюда. Или добавьте мое облако похорон WeChat и учитесь вместе.

ссылка

унарный оператор
Переучи js - унарный оператор (delete/void/typeof/+/-/~/!)
Глубокое понимание оператора удаления в JavaScript
Углубленный анализ удаления
Некоторые приложения ~, &, |, ^ и других побитовых операторов в JavaScript
Помните воспоминание о собеседовании в школе, запоздалом брифинге бит-оператора
implicit.js