Прежде чем писать в этот блог, я хочу рассказать об одной вещи, на которую я обратил внимание сегодня (28 марта 2019 г.) (ради приобщения к веселью - стыдно). Вчера незаметно появился сайт под названием Github, крупнейший в мире сайт знакомств.996.ICUПроект документа, весь проект не имеет кода, просто перечислены некоторые статьи «Закона о труде» и компания, которая недавно указала, что внедрена система работы 996. Я думал, что этоласкиЯ пожаловался, но когда я снова посмотрел его сегодня в полдень, количество звезд уже было там.30kвыше, и вопросы достигают5000+. после полудняКак сломанный бамбук, в звездном рейтинге Github, на протяжении всего пяти уровней и шести генералов, пока что это меньше, чем24 часапроекты, с63kзвезда и таблица лидеров21-й. Почему возник такой простой проект, сопровождаемыйТу БангПоза вышла из-под контроля. Может быть, это просто тронуло самые чувствительные нервы в сердцах друзей, которые были вынуждены работать в 996, и программистов, которые работали бесконечно сверхурочно без вознаграждения. явилась реальность Когда мир позволяет тебе изливаться сколько угодно, горькая вода в твоем сердце выливается наружу, создавая этостранныйс проект. Дело не в том, что мы не можем принять 996, а в том, что для внедрения системы работы 996 компания должна платить соответствующее вознаграждение, что дает сотрудникам ощущение, что их усилия вознаграждаются, нет ни соответствующего вознаграждения, ни собственного времени, а обида будет только увеличить больше. Что мы можем теперь сделать:1. Старайтесь не ходить в 996 компаний, чтобы в 996 компаниях некого было нанимать 2. Повысьте свой технический уровень и позвольте себе доминировать в торгах.Если вам придется внедрить 996, вы можете договориться о зарплате, которую вы можете принимать.. Вышесказанное является моим личным мнением, если вам не нравится, не распыляйте. (такая же фраза... если деньги на месте, то можно и в компании жить)
Что это?
Что это? что это? что это? (Чёрный знак вопроса)
Сегодняшняя тема (😍?)call、applyтак же какbind, здесьтак же какЯ думаю, что это работает хорошо, я объясню, почему нетbindа такжеcall、applyсгруппированы в одну категорию.
thisОбъекты связываются во время выполнения в зависимости от среды выполнения функции.(Оставьте функции стрелок в стороне)
Когда функция вызывается как метод некоторого объекта,thisравный этому объекту
thisравен объекту, который последний раз вызывал функцию
Вот например ⬇️
var name = 'Jack Sparrow';
function sayWhoAmI() {
console.log(this.name)
}
sayWhoAmI(); // Jack Sparrow
var onePiece = {
name: 'Monkey·D·Luffy',
sayWhoAmI: function () {
console.log(this.name)
}
};
onePiece.sayWhoAmI(); // Monkey·D·Luffy
Из приведенного выше кода видно, что независимо от того, где он определенsayWhoAmI()метод, тело функции такое же,onePiece.sayWhoAmI()Из вышеизложенного можно понять, что:
∵ (потому что то же самое ниже) последний объект, вызывающий метод,onePiece
∴ (то же самое ниже)thisдаonePiece,this.nameто естьonePiece.name
Но почему он определяется глобальноsayWhoAmIНа выходе метода Джек Воробей, так что если я изменю способ написания, то все поймут ⬇️
var name = 'Jack Sparrow';
function sayWhoAmI() {
console.log(this.name)
}
- sayWhoAmI(); // Jack Sparrow
+ window.sayWhoAmI(); // Jack Sparrow
Это понятно
∵ Переменные или функции, объявленные глобально,windowилиglobleв этом объекте
∴ вwindowобъявлен глобальноsayWhoAmIможет выводить то же самоеwindowобъявлен глобальноname
небольшой продвинутый
Просто, мы уже поняли, теперь давайте рассмотрим добавлениеreturnЯ думаю, что это немного сложно использовать метод, пожалуйста, проходите мимо ⬇️
var area = 'East Ocean';
var onePiece = {
area: 'New World',
tellMeWhereAreYou: function () {
return function () {
console.log(this.area);
}
}
};
onePiece.tellMeWhereAreYou()(); // East Ocean
// 如果看不懂这里为什么执行两次,或者不明白为什么输出的全局变量
// 那我引入一个中间变量,让过程多一步就能看懂了
var grandLine = onePiece.tellMeWhereAreYou();
// 这时候的 grandLine = function() { console.log(this.area); },等于onePiece.tellMeWhereAreYou();返回的函数
// 因为grandLine是一个全局变量,所以this.area返回的是East Ocean
grandLine(); // East Ocean
Выше я думаю, что объяснил эту проблему кратко и всесторонне, потому что это включает в себя знание замыканий и активного объекта функций, Если вы не понимаете, вы можете прочитать мой другой блог.«Front-end сразится с пятью подонками, чтобы выучить JavaScript — закрытие», Если вы все еще этого не понимаете и хотите получить более глубокое понимание, вы можете самостоятельно прочитать главу 7.2 «Расширенное программирование на JavaScript» и понять две картинки в главе 7.2.
Итак, теперь вопрос в том, как я могу заставить эту функцию выводить внутреннюю часть моего объекта.area: 'New World'⬇️
var area = 'East Ocean';
var onePiece = {
area: 'New World',
tellMeWhereAreYou: function () {
var that = this;
// 我们通过声明一个变量来保存this所指向的对象,然后再闭包中,就是返回的函数中使用
// 一个典型的闭包结构就完成了
return function () {
console.log(that.area);
}
}
};
onePiece.tellMeWhereAreYou()(); // New World
Возможно, вы будете использовать промежуточные переменные в своей предыдущей работе, чтобы сэкономитьthisЭтот метод, а я не считаю его сложным, то пропускаю.
У нас уже должно быть общее представлениеthisуказал на проблему. Но мы извращенцы, мы больны, мы наконец-то это понялиthisуказывая на проблему, то теперь мы хотим изменитьthisТочка, 😜Жизнь везде трудна
На этот раз нам нужно использовать упомянутые в заголовкеcallа такжеapply
Apply nothing and just call me
call()метод сapply()методтот же эффект, они отличаются только способом получения параметров. ——————《Расширенное программирование на JavaScript》
В книге очень ясно, что у них обоих одна и та же функция, но метод получения параметров разный. Так в чем же разница? Послушайте меня, и я объясню подробно.
сумасшедший звонок
call()метод может указатьthisЗначение функции (первый параметр) и параметры передаются соответственно (параметры после первого параметра — это параметры, которые необходимо передать в функцию, которые необходимо передавать один за другим)
call()Какая польза от метода, конечно же, для решения только что предложенных нами измененийthisТочка, как это использовать? ? ? ⬇️
var first = '大黑刀·夜',
second = '二代鬼彻',
third = '初代鬼彻',
fourth = '时雨';
var zoro = {
first: '和道一文字',
second: '三代鬼彻',
third: '雪走',
fourth: '秋水'
};
function sayYourWeapon(num, num2) {
console.log(`这是我${num}得到的刀"${this[num]}"`)
console.log(`这是我${num2}得到的刀"${this[num2]}"`)
}
sayYourWeapon('first', 'third'); // 这是我first得到的刀"大黑刀·夜";这是我third得到的刀"初代鬼彻"
sayYourWeapon.call(zoro, 'first', 'fourth'); // 这是我first得到的刀"和道一文字";这是我fourth得到的刀"秋水"
Приведенный выше код явно изменилсяthis, если я позвоню напрямуюsayYourWeapon()Неизбежным выходом является глобальная глобальная переменнаяfirstа такжеthirdзначение, и я передаюsayYourWeapon.call(zoro, 'first', 'fourth')серединаcall()метод
∵ изменена функция вthisзначение, которое передается вzoro,ПучокthisЗначение было изменено с глобального объекта наzoroобъект
∴ Следующий вывод также является объектомzoroсередина'first', 'fourth'значение
применять все конфигурации
apply()метод может указатьthisЗначение (первого параметра) и передать массив параметров (параметры должны быть в виде массива или массива, подобного массиву)
Мы уже должны знатьcall()Как использовать метод, то мы знакомы сapply()Это намного проще, мы можем изменить приведенный выше пример ⬇️
var first = '大黑刀·夜',
second = '二代鬼彻',
third = '初代鬼彻',
fourth = '时雨';
var zoro = {
first: '和道一文字',
second: '三代鬼彻',
third: '雪走',
fourth: '秋水'
};
function sayYourWeapon(num, num2) {
console.log(`这是我${num}得到的刀"${this[num]}"`)
console.log(`这是我${num2}得到的刀"${this[num2]}"`)
}
sayYourWeapon('first', 'third'); // 这是我first得到的刀"大黑刀·夜";这是我third得到的刀"初代鬼彻"
- sayYourWeapon.call(zoro, 'first', 'fourth'); // 这是我first得到的刀"和道一文字";这是我fourth得到的刀"秋水"
+ sayYourWeapon.apply(zoro, ['first', 'fourth']); // 这是我first得到的刀"和道一文字";这是我fourth得到的刀"秋水"
Как видите, я просто поставилcallизменился наapply, и поставить перед'first', 'fourth'Передаваемые таким образом параметры изменяются на['first', 'fourth']массив. Если мы используем его в функции, мы также можем использовать его напрямую.argumentsЭтот массивоподобный объект ⬇️
var first = '大黑刀·夜',
second = '二代鬼彻',
third = '初代鬼彻',
fourth = '时雨';
var zoro = {
first: '和道一文字',
second: '三代鬼彻',
third: '雪走',
fourth: '秋水'
};
function sayYourWeapon(num, num2) {
console.log(`这是我${num}得到的刀"${this[num]}"`)
console.log(`这是我${num2}得到的刀"${this[num2]}"`)
}
function mySayYourWeapon(num, num2) {
sayYourWeapon.apply(zoro, arguments) // 我们自己声明一个函数,并且在里面调用apply,这是我们只需要传入arguments这个参数,而不需要想call那样一个一个传进去了
}
sayYourWeapon('first', 'fourth'); // 这是我first得到的刀"大黑刀·夜";这是我fourth得到的刀"时雨"
mySayYourWeapon('first', 'fourth'); // 这是我first得到的刀"和道一文字";这是我fourth得到的刀"秋水"
Связать секрет
Я говорил об этом в начале статьи⬇️
call、applyтак же какbind, здесьтак же какя думаю, что это работает хорошо
Теперь поговорим о значении этого «и».
Почему я говорю «и», потому чтоbindа такжеcall、applyИспользование этих двух методов немного отличается. Выше мы вызываем функцию.call()или.apply()метод, метод будет выполнен сразу, если у функции есть возвращаемое значение, то будет получено возвращаемое значение, ноbindРазные
Метод bind() не сразу выполняет целевую функцию, а возвращает копию исходной функции с указаннымthisЗначение и начальная функция (почему указано, конечно, мы передаем в себя)
Что такое копия оригинальной функции, давайте сначала разберемся⬇️
function a() {}
console.log(typeof a.bind() === 'function'); // 返回是true,先证明a.bind()是一个函数
console.log(a.bind()); // 输出function a() {},跟原函数一样
console.log(a.bind() == a); // false
console.log(a.bind() === a); // false 不管是 === 还是 == 都是false,证明是拷贝出来一份而不是原先的那个函数
Проблема «копирования исходной функции» описана выше, давайте посмотримbind()как использовать
подготовка к печати
bind()За методом следует переданный параметрcallТо же самое, первым параметром является объект, который нужно связать, а параметры, требуемые функцией, передаются позже, следующим образом⬇️
var name = 'Jack Sparrow';
var onePiece = {
name: 'Monkey·D·Luffy'
};
function sayWhoAmI() {
console.log(this.name)
}
var mySayWhoAmI = sayWhoAmI.bind(onePiece)
sayWhoAmI(); // Jack Sparrow
mySayWhoAmI(); // Monkey·D·Luffy
Простая реализация, которая первоначально выводила глобальную переменную «Джек Воробей», позже переданнуюbindПосле привязки объектаonePiece, так что выходом является объектonePieceсерединаnodeОбезьяна d Луффи.
тогда мынужно передать параметрыЧто делать, когда ⬇️
var first = '大黑刀·夜',
second = '二代鬼彻',
third = '初代鬼彻',
fourth = '时雨';
var zoro = {
first: '和道一文字',
second: '三代鬼彻',
third: '雪走',
fourth: '秋水'
};
function sayYourWeapon(num, num2) {
console.log(`这是我${num}得到的刀"${this[num]}"`)
console.log(`这是我${num2}得到的刀"${this[num2]}"`)
}
// 既然我们知道bind是返回一个函数,那我们声明一个变量来接这个函数会看的直观一些
var mySayYourWeapon = sayYourWeapon.bind(zoro, 'first', 'fourth'); // 传入初始参数
var hisSayYourWeapon = sayYourWeapon.bind(zoro); // 只传入目标对象
sayYourWeapon('first', 'third');
mySayYourWeapon(); // 因为我们当时bind绑定函数的时候已经传入了目标对象zoro和指定的参数,所以这里就不需要传参数了
hisSayYourWeapon( 'first', 'fourth'); // 当然我们开始bind绑定函数的时候不传入,在调用的时候再传入参数也是可以的
В приведенном выше коде мы можем найтиmySayYourWeaponа такжеhisSayYourWeaponсуществуетbindКогда один передается в начальном параметре, другой не передается, но его можно снова передать в последующих вызовах.
Так как это параметр инициализации, то мы можем установить один параметр, а затем передать частичную функцию (не знаю, правильно ли я понимаю, но такая функция должна быть, если вы не понимаете, вы можете переместитьЧастичные функции в Function.prototype.bind из веб-документов MDN)
Печать окончена, пора действовать
теневая мимика
По умолчанию все здесь уже умеют им пользоватьсяbindТеперь нам нужно бросить вызов следующему: написать его самостоятельно.bindметод, это может помочь нам лучше понятьbindКак работает метод, а также может быть задан вопрос во время интервью~
Ниже мы рассмотримFunction.prototype.bind из веб-документов MDNЯ скопировал реализацию из , и добавил свое понимание и комментарии, надеюсь вы поняли ⬇️
// 判断当前环境的Function对象的原型上有没有bind这个方法,如果没有,那我们就自己添加一个
if (!Function.prototype.bind) {
/**
* 添加bind方法
* @param oThis 目标对象
* @returns {function(): *} 返回的拷贝函数
*/
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
// closest thing possible to the ECMAScript 5
// 最接近ECMAScript 5的实现(貌似是这个意思)
// internal IsCallable function
// 内部IsCallable函数(🙄什么鬼)
// 如果当前this对象不是function,就抛出错误,因为只有function才需要实现bind这个方法。。。毕竟是返回函数
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
// 声明变量aArgs保存arguments中除了第一个参数的其他参数的数组,因为第一个参数不是函数需要的参数,而是需要绑定的目标对象
// 这块就用到了call的方法,因为arguments是类数组对象,没有slice这个方法,所以只能从Array那call过来一个使用
var aArgs = Array.prototype.slice.call(arguments, 1);
// 保存原先的this对象,是在调用bind的时候没有传入目标对象,那就使用原先的this对象
var fToBind = this;
// 声明空函数,在下面的原型中可以使用
var fNOP = function() {};
// 需要放回的拷贝函数的本体,从最后的return也知道,最后是返回的fBound这个方法
var fBound = function() {
// this instanceof fBound === true时,说明返回的fBound被当做new的构造函数调用
// 下面就涉及到刚才说的是bind时初始化参数,还是bind以后调用的时候再传入参数
return fToBind.apply(
// 判断原始this对象是不是fBound的实例,或者说this的原型链上有没有fBound
this instanceof fBound
// 如果有,就使用原始的this
? this
// 如果没有,就使用现在的传入的this对象
: oThis,
// 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
// 这一步就是为了保障在bind时候没有传入参数的时候,调用时候传入的参数能使用上
aArgs.concat(Array.prototype.slice.call(arguments)));
};
// 维护原型关系
// 判断原始this对象上有没有prototype
if (this.prototype) {
// Function.prototype doesn't have a prototype property
// 如果原始this对象上有prototype 就把fNOP的prototype改成this.prototype,fNOP就继承自原始this了
fNOP.prototype = this.prototype;
}
// 下行的代码使fBound.prototype是fNOP的实例,因此
// 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
// 既然fNOP是继承自原始this对象的,那这里的这一步就是让拷贝函数也拥有原始this对象的prototype,继承自同一个地方,师出同门
fBound.prototype = new fNOP();
// 最后返回被拷贝出来的函数
return fBound;
};
}
Я добавил комментарии в приведенный выше код, чтобы каждый мог лучше понять, разобравшись с приведенным выше кодом,bindМетод почти понятен, и другие принципы реализации понятны.
Возможно комментарии выше кода многовато, выглядит очень трудоемко, ниже выложен код без комментариев, чтобы можно было скопировать и вставить отладку
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments, 1);
var fToBind = this;
var fNOP = function() {};
var fBound = function() {
return fToBind.apply(this instanceof fBound ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
};
if (this.prototype) {
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP();
return fBound;
};
}
Так что кажется, что кода не так уж много для достиженияbindметод
Мечты людей никогда не закончатся, верно?
возможно996.ICUЭто не может играть существенной роли, но дайте нам знать, что есть группа прекрасных людей, которые так же, как и мы, усердно трудятся, чтобы заработать на жизнь, дайте нам знать, что наш круг не мал, но когда он не сплочен, он Не плохо осмелиться бросить, люди должны быть Если вы хотите мечтать, пока вы молоды, в случае, если это сбудется.
Блог во время болезни. . .
ps: Блоги могут делиться технологиями, и их также можно использовать для записи жизни.Если вы увидите это позже, вы можете сказать: "Это глупо в то время", но сейчас я чувствую себя прекрасно
Я первопроходец войны пятерки, ученик начальной школы в мире фронтенда.