Некоторые непопулярные операции js

внешний интерфейс JavaScript React.js jQuery

Эта статья взята из моегоgithub

0. Предисловие

Когда все учатся, когда они сначала новички, а потом, когда соприкасаются с продвинутыми вещами, они находят, что все удобно, и некоторые люди могут начать говорить, что они опытные. Внезапно однажды я обнаружил несколько дерзких операций, основанных на очень простых вещах, и начал сомневаться в жизни: что за JavaScript? Если вы не были поражены чем-то или не видели новый мир, может быть, навсегда, вы вздохнете: jQuery настолько прост в использовании, я хорошо разбираюсь в jQuery и хорошо разбираюсь в js. Или вью? угловатый? реагировать? Я буду, я опытный.

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

1. Массив

Аналогично некоторым видам обхода apis: forEach, map, некоторые люди могут сказать: нетarr.map(x=>x+1), если задействован индекс, то другой индекс,arr.map((x,index)=>x+index), насколько это просто? Затем начните с плохого вопроса на собеседовании:['1','2','3'].map(parseInt)Люди ищут работу, читают вопросы на собеседовании и знают, что результат [1, нан, нан], тогда почему? Во-первых, карта может передавать два параметра: Карта (вызывается функция каждого элемента, ЭТО значение функции) Вызывается функция каждого элемента, а его входными параметрами являются текущие элементы (обязательные), индексы, массивы.

1.1 Вы владеете parseInt?

В этом примере эти три параметра передаются в parseInt. Для нативной функции parseInt параметры, которые она передает, следующие (число, основание): radix представляет основание числа для анализа. Значение находится в диапазоне от 2 до 36. Если этот параметр опущен или его значение равно 0, число будет анализироваться по основанию 10. Если он начинается с «0x» или «0X», это будет основание 16. parseInt() вернет NaN, если аргумент меньше 2 или больше 36.

parseInt(10,10)//对10进制数字10取整,10
parseInt(10,2)//对2进制数字10取整,2
parseInt(111,2)//对2进制数字111取整,7
parseInt(111,4)//对4进制数字111取整,21
parseInt('1',2,[1])//1,传入第三个数组是没有意义的
parseInt('1',2,['1','2','3','4'])//1
parseInt('2',2,['1','2','3','4'])//NaN,2进制没有2
parseInt('2',3,['1','2','3','4'])//3

Понятно, почему [1,NaN,NaN], на самом деле:

parseInt('1',0,['1','2','3'])//1,radix为 0,则数字将以 10 为基础来解析
parseInt('2',1,['1','2','3'])//1进制是啥?反正就是NaN
parseInt('3',2,['1','2','3'])//2进制没有3

Кроме того, parseInt попытается интерпретировать номер строки, когда встретит ее, и остановится до тех пор, пока ее нельзя будет интерпретировать.

parseInt('123sfd')//123
parseInt('123sfd123')//123
parseInt('sfd213')//NaN

1.2 Второй параметр API для обхода массива

Второй параметр представляет this внутри предыдущей функции, обычно этот параметр не заполняется, в строгом режиме это не определено. В нестрогом режиме это указывает на окно:[1,2,3].forEach(function(x){console.log(this)})//windowМы можем насильственно изменить его на что-то еще и посмотреть:[1,2,3].forEach(function(x){console.log(this)},Math)//Math

1.3 Позвольте массиву стать усовершенствованным

Мы знаем, что Array может напрямую генерировать массив со всеми пустыми элементами определенной длины: Array(5)//Обратите внимание, 5 пустых и 5 неопределенных значений отличаются Можно также применить:

Array.apply(null, { length:5 })// [undefined, undefined, undefined, undefined, undefined]
Array.apply(null, { '0':1,length:5 })// [1, undefined, undefined, undefined, undefined]
Array.apply(null, { '2':1,length:5 })// [undefined, undefined, 1, undefined, undefined]

Эквивалентно непосредственному изменению атрибутов только что созданного массива

1.4 Используете ли вы цикл для создания последовательности?

Создайте порядковый массив:

var arr = [];
for(var i = 0;i<10;i++){
    arr.push(i)
}

С нормальной работой проблем нет, но будете ли вы использовать другие методы, если хорошо разбираетесь в jQuery? Например:

Array.apply(null, {length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],f可以是任何函数
Array.apply(null, { '0':1,length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],不管元素是什么都一样
Array.apply(null, {length:5 }).map(f.call,Boolean)//[false, true, true, true, true]
Array.apply(null, {length:5 }).map(f.call,String)//["0", "1", "2", "3", "4"]
Array.apply(null, {length:5 }).map(eval.call,Object)//[Number, Number, Number, Number, Number]

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

1

Функция карты передает три параметра, первый параметр — текущий элемент. Но для добавленного звонка первым параметром является эта точка звонка. Параметр за картой такой, то есть текущий this был покрыт последним, и последний параметр играет ведущую роль. Первый параметр fn карты, второй параметр в fn — это индекс, который является текущим индексом. Для f.call первым параметром является этот указатель, а вторым и последующими параметрами являются все параметры, используемые функцией f из f.call. Наконец, это эквивалентно выполнению для каждого элемента: число (индекс), логическое значение (индекс), строка (индекс), объект (индекс).

2. Битовые операторы

Основное использование и концепции обсуждаться не будут, просто прочитайте документацию самостоятельно.

2.1 Строка в число

Существует parseInt, о котором знает весь мир, но мы можем использовать более простой метод:

//就是让他进行不改变本身的值的数学运算
+"1"
"1"*1
"1"|0
"1" >> 0
"1" << 0

2.2 Дополнительные операции

Если мы хотим получить большое число по желанию, то обычно это 9999*9999, а операция смещения может быть эквивалентна умножению на 2 в степени n:1<<30//1073741824Кажется бесполезным, сначала кидайте требование: случайным образом генерировать строку (цифра + буква) Я знаю, что многим вообще не нужно думать, просто взять клавиатуру и шлепнуть: Например, сгенерировать 6-значную случайную строку

var n = 6
var str = 'abcdefghijklmnopqrstuvwxyz0123456789'
var result = ''
for (var i = 0 ;i<n;i++){
   result += str[parseInt(Math.random()*(str.length+1))]
}

Для битовых манипуляций это короткое кодовое решение:

(~~(Math.random()*(1<<24))).toString(16)
(~~(Math.random()*(1<<30))).toString(36)

Сначала сгенерируйте большое число, а затем преобразуйте его в базовое. Шестнадцатеричный код — это 0-9 плюс первые несколько букв, а 36-шестнадцатеричный — это 0-9 плюс 26 символов, тогда мы можем получить стабильную версию генерации n-значных случайных строк:

function f(n){
	if(n==1) return (~~(Math.random()*36)).toString(36)
	return (~~(Math.random()*36)).toString(36) + f(n-1)
}
//尾递归优化
function k(n){
	return function f(n,s){
		if(n==1) return s
		return  f(n-1,(~~(Math.random()*36)).toString(36)+s)
	}(n,(~~(Math.random()*36)).toString(36))
}

Другой способ: (также основанный на высокой базе) мы можем начать сMath.random().toString(36)Получите строку с 11 знаками после запятой после 0.xxx, поэтому нам нужно взять только вторую цифру и позже.Math.random().toString(36).slice(2)

Давайте немного прервемся

Для обсессивно-компульсивного расстройства, преследующего крайне короткий код, увидев if-else выше, я вдруг вспоминаю, что обычно пишу много if-else, что очень не радует глаз. короткие тернарные выражения, у нас также есть краткие выражения: || && a&&b: верно a, переходим к b a||b: a ложно, запустить b, если a верно, взять a

//来一个有点智障的例子
function f(a){
if(a==1) console.log(1)
if(a==2) console.log(2)
if(a==3) console.log(3)
}

//一定要记得写分号
function f(a){
(a==1)&& console.log(1);
(a==2) &&console.log(2);
(a==3) &&console.log(3);
}

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

Поменять местами два целых числа с помощью битовых операций

Сложение и вычитание для обмена без промежуточных переменных а = а+б, б = а-б, а = а-б С битовыми манипуляциями: а ^ = б; б ^= а; а ^ = б;

Конкретный процесс можно доказать следующим образом:

我们先令a0 = a, b0 = b。a = a ^ b 可以转化为a = a0 ^ b
第二句:b = b ^ a =  b0 ^ a = b0 ^ (a0 ^ b0) = a0 ^ (b0 ^ b0) = a0 ^ 0 = a0//达到了原始值a0和实际值b交换
第三句一样:a = a ^ b = a ^ (b0 ^ a) = b0 ^ (a ^ a)= b0 ^ 0 = b0,和原始的b0交换成功

3. Создайте класс

Продолжайте возвращаться к предыдущему примеру:

Array.apply(null, {length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],f可以是任何函数
Array.apply(null, { '0':1,length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],不管元素是什么都一样
Array.apply(null, {length:5 }).map(f.call,Boolean)//[false, true, true, true, true]
Array.apply(null, {length:5 }).map(f.call,String)//["0", "1", "2", "3", "4"]
Array.apply(null, {length:5 }).map(eval.call,Object)//[Number, Number, Number, Number, Number]

Второй параметр ctx карты — это эта точка, а первый параметр — это функция f (любая функция), первый параметр f был убран, потому что первый параметр — это контекст вызова this, но это позже. заменяется, поэтому эффективные параметры f начинаются со второго, и, наконец, он эквивалентен ctx (index), то есть: класс построения (index)

Так что можем посмотреть еще одно интересное место в строительном классе

var toFixed = 1;
var obj = {
     toFixed:"我只是客串的",
    show:function(){
        return this. toFixed;
    }
}
obj.show.call( toFixed);   //ƒ toFixed() { [native code] }

Возможно, на первый взгляд это выглядит как 1, но первый параметр call не равен null или undefined, поэтому эффект другой. Контекст нашего вызова toFixed. Таким образом, можно понять, что для внутренней части js 1 фактически конструируется классом построения Number (1), что эквивалентно этому указанию на Number, и мы можем напечатать Number.prototype, и результат

1
Распечатываем метод toFixed

Также возможно для строки

var big = '1sdasdsadsdasd';//不是字符串的话,其他构造类没有big方法,返回undefined
var obj = {
    big:"我是客串的",
    show:function(){
        return this.big;
    }
}
obj.show.call(big);  //ƒ big() { [native code] }

//或者说,打印一个length看看
var l = '1sdasdsadsdasd';//变量换成l
var obj = {
    length:"我是客串的",
    show:function(){
        return this.length;//主要是这个,变量是什么不重要
    }
}
obj.show.call(l); //14

Слишком много свойств, можно зайти в консоль посмотреть, что есть у String.prototype.

Или посмотрите, что происходит, когда функция выполняется:

var l = true;//这次试一下boolean类型
var obj = {
    length:"我是客串的",
    show:function(){
        return this.valueOf();//这次我们不打印这个函数了,让他执行
    }
}
obj.show.call(l,this); //true,直接调用类型转换过程中的那个valueOf

Причина та же, каждый может вернуться и поиграть