2016-06-19 6 views
2

This code из мангуст-глубоководные заселитьJavaScript привязывать против анонимной функции

async.parallel([ 
    User.create.bind(User, {_id: 1, manager: 2, mainPage: 1}), 
    Comment.create.bind(Comment, {_id: 3, user: 1}), 
    ... 
], cb) 

использует Function.prototype.bind, чтобы гарантировать, что this привязан к соответствующему объекту, если функция обратного вызова User.create выполняется в другом контексте. Является ли это эквивалентом

async.parallel([ 
    function() { User.create({_id: 1, manager: 2, mainPage: 1}) }, 
    function() { Comment.create({_id: 3, user: 1}) }, 
], cb) 

?

Если да, то в какой ситуации bind более предпочтительный синтаксис по сравнению с использованием анонимной функции?

+2

Это будет вопрос мнения и под влиянием реальной ситуации. –

+0

_Is это эквивалент? _ Да, в этом случае анонимные функции эквивалентны использованию. .bind() ' –

+1

Термин« лямбда »обычно не используется для анонимных функций JS. – JJJ

ответ

2

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

function mul(num, times) { 
    return num * times; 
} 

function fn1() { 
    let num = 3; 

    let cb = function(times) { 
     return mul(num, times); 
    } 

    num = 5; 
    console.log(`num is now: ${ num }`); 

    return cb; 
} 

function fn2() { 
    let num = 3; 

    let cb = mul.bind(null, num); 

    num = 5; 
    console.log(`num is now: ${ num }`); 

    return cb; 
} 

При запуске двух вы получите разные результаты :

let a1 = fn1()(5); // a1 === 25 
let a2 = fn2()(5); // s2 === 15 

разница между ними состоит в том, что при использовании bind свяжут текущие значения функции (в качестве параметров), а при использовании анонимной функции используемых значений будут те, которые существуют при вызове функции ,

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

var a = ["zero", "one", "two", "three", "four", "five"]; 
function fn(value, index) { 
    console.log(value, index); 
} 

// doesn't work as i is undefined when the function is invoked 
for (var i = 0; i < a.length; i++) { 
    setTimeout(() => { 
     fn(a[i], i); 
    }, 45); 
} 

// works because the value of i and the value of a[i] are bound 
for (var i = 0; i < a.length; i++) { 
    setTimeout(fn.bind(null, a[i], i), 45); 
} 

(пример с анонимной функции будет работать, если вы используете let вместо var)

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

let counter = { 
    _current: 0, 
    get: function() { 
     return this._current++; 
    } 
} 

let map = { 
    _items: Object.create(null), 
    set: function(key, value, index) { 
     this._items[key] = { 
      index: index, 
      value: value 
     } 
    } 
} 

// using anonymous functions the index in most cases won't reflect the real order 
setTimeout(function() { 
    map.set("one", 1, counter.get()); 
}, Math.floor(Math.random() * 1500) + 100); 
setTimeout(function() { 
    map.set("two", 2, counter.get()); 
}, Math.floor(Math.random() * 1500) + 100); 
setTimeout(function() { 
    map.set("three", 3, counter.get()); 
}, Math.floor(Math.random() * 1500) + 100); 

// using bind, the index will always be correct 
setTimeout(map.set.bind(map, "one", 1, counter.get()), Math.floor(Math.random() * 1500) + 100); 
setTimeout(map.set.bind(map, "two", 2, counter.get()), Math.floor(Math.random() * 1500) + 100); 
setTimeout(map.set.bind(map, "three", 3, counter.get()), Math.floor(Math.random() * 1500) + 100); 

r r eason это работает по-другому, так как при связывании counter.get() получает оценку до того, как функция bind вызывается, поэтому правильное возвращаемое значение привязано.
При использовании анонимной функции counter.get() оценивается только при выполнении функции, и порядок ее анонимной функции неизвестен.

 Смежные вопросы

  • Нет связанных вопросов^_^