Правила этой привязки можно прочитать
Что делать, если сайт вызова имеет несколько правил приемлемости? Таким образом, должен существовать порядок приоритета правил.
Примечание. — По умолчанию имеет самый низкий приоритет.
Что является более прецедентным? неявное или явное?
Consider the below code snippet: -
function test(){
console.log("precedence test");
}
var obj1 = {
a:10,
test: test
};
var obj2 = {
a:20,
test: test
};
obj1.test();//10
obj2.test();//20
obj1.test.call(obj2);//20
obj2.test.call(obj1);//10
Здесь мы видим, что явное связывание имеет больший приоритет, чем неявное.
Что является более прецедентным? неявное или новое?
Consider the below code snippet: -
function test(data){
this.a = data;
}
var obj1 = {
test: test
};
var obj2 = {};
obj1.test(2);
console.log(obj1.a)//2
obj1.test.call(obj2,3);
console.log(obj2.a)//3
var newBinding = new test(100);
console.log(obj1.a);//2
console.log(newBinding.a);//100
Таким образом, новая привязка является более приоритетной, чем неявная привязка.
Как насчет новой привязки и явной привязки?
new и call/apply не могут применяться вместе, поэтому новая привязка test.call(obj1) не может напрямую тестировать новую привязку против явной привязки.
Что же тогда делать? Hard Binding приходит на помощь. Используя жесткую привязку, мы можем проверить приоритет двух правил.
Consider the below code snippet: -
function test(data){
this.a = data;
}
var obj1 = {};
var test1 = test.bind(obj1);
test1(2);
console.log(test1.a);//2
var newBinding = new test1(3);
console.log(obj1.a);//2
console.log(newBinding.a);//3
test1 is hard bounded with obj1. but new test1(3) did not change obj1.a to 3, instead hard bounded call to test1(2) is able to be overridden with new.
Более подробную информацию о привязке можно найти на
Давайте подведем итоги
- Вызывается ли функция с новым (новая привязка)? Если это так, это вновь созданный объект.
var test1 = new test(3); - Вызывается ли функция с вызовом или применением (явная привязка), даже скрытая внутри жесткой привязки? Если да, это явно указанный объект.
var test1 = test.call(obj); - Если функция вызывается в контексте (неявная привязка), это будет содержащий объект.
var test1 = obj.test(); - Если правило не применимо, применяется значение по умолчанию. Если в строгом режиме, выберите undefined, в противном случае выберите глобальный объект.
var test1 = test();
На этом мы закончили, я бы сказал, почти завершая статью. Подождите, могут ли быть некоторые сценарии, в которых мы в конечном итоге привязываем поведение по умолчанию?
Игнорировал это
Если вы передаете null или undefined в качестве параметра привязки для вызова, применения или привязки, эти значения фактически игнорируются, и применяется правило по умолчанию.
function ignored(){
console.log(this.a);
}
var a = 2;
ignored.call(null);//2
Вместо передачи null создайте пустой объект и передайте его в качестве параметра.
function ignored(a,b){
console.log(this.a,this.b);
}
var dummyObject = Object.create(null);
//spread out array as params
ignored.apply(dummyObject,[2,3]);//a:2,b:3
//currying with bind
var curryExample = ignored.bind(dummyObject,2);
curryExample(3);//a:2,b:3
Косвенная ссылка
Мы можем случайно создать «косвенные ссылки» на функции. Когда эта ссылка на функцию вызывается, применяется правило привязки по умолчанию.
'use strict';
function indirectTest() {
console.log(this.a);
}
var a = 2;
var obj = {
a: 3,
indirectTest: indirectTest
};
var anotherObject = {
a: 4
};
obj.indirectTest();
anotherObject.indirectTest = obj.indirectTest;
indirectTest();
Лексическое это
Обычные функции JS подчиняются 4 правилам. Но ES6 вводит особый вид функции — стрелочную функцию, которая не использует эти правила.
Функция стрелки использует оператор «толстая стрелка» =>. Вместо использования 4 правил используется "эта привязка" из объемлющей функции или глобальной области.
function lexicalSample(){
return (a) => {
console.log(this.a);
};
}
var obj1 = {
a: 2
};
var obj2 = {
a: 3
};
var sample = lexicalSample.call(obj1);
sample.call(obj2);//2 not 3