'without' 函数在集合上做什么?
What is the 'without' function doing on a collection?
这是一个 backbone 教程。这是代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>To-do App in Backbone.js</title>
<!-- ========= -->
<!-- CSS -->
<!-- ========= -->
<style type="text/css">
#todoapp ul {
list-style-type: none; /* Hides bullet points from todo list */
}
#todo-list input.edit {
display: none; /* Hides input box*/
}
#todo-list .editing label {
display: none; /* Hides label text when .editing*/
}
#todo-list .editing input.edit {
display: inline; /* Shows input text box when .editing*/
}
</style>
</head>
<body>
<!-- ========= -->
<!-- Your HTML -->
<!-- ========= -->
<section id="todoapp">
<header id="header">
<h1>Todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus>
<div>
<a href="#/">show all</a> |
<a href="#/pending">show pending</a> |
<a href="#/completed">show completed</a>
</div>
</header>
<section id="main">
<ul id="todo-list"></ul>
</section>
</section>
<div>
<p>Find the tutorial and code in <a href="http://adrianmejia.com/blog/2012/09/11/backbone-dot-js-for-absolute-beginners-getting-started/">here</a></p>
</div>
<!-- Templates -->
<script type="text/template" id="item-template">
<div class="view">
<input class="toggle" type="checkbox" <%= completed ? 'checked' : '' %>>
<label><%- title %></label>
<input class="edit" value="<%- title %>">
<button class="destroy">remove</button>
</div>
</script>
<!-- ========= -->
<!-- Libraries -->
<!-- ========= -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.0/backbone.localStorage-min.js" type="text/javascript"></script>
<!-- =============== -->
<!-- Javascript code -->
<!-- =============== -->
<script type="text/javascript">
'use strict';
var app = {}; // create namespace for our app
//--------------
// Models
//--------------
app.Todo = Backbone.Model.extend({
defaults: {
title: '',
completed: false
},
toggle: function(){
this.save({ completed: !this.get('completed')});
}
});
//--------------
// Collections
//--------------
app.TodoList = Backbone.Collection.extend({
model: app.Todo,
localStorage: new Store("backbone-todo"),
completed: function() {
return this.filter(function( todo ) {
return todo.get('completed');
});
},
remaining: function() {
debugger;
return this.without.apply( this, this.completed() );
}
});
// instance of the Collection
app.todoList = new app.TodoList();
//--------------
// Views
//--------------
// renders individual todo items list (li)
app.TodoView = Backbone.View.extend({
tagName: 'li',
template: _.template($('#item-template').html()),
render: function(){
this.$el.html(this.template(this.model.toJSON()));
this.input = this.$('.edit');
return this; // enable chained calls
},
initialize: function(){
this.model.on('change', this.render, this);
this.model.on('destroy', this.remove, this); // remove: Convenience Backbone's function for removing the view from the DOM.
},
events: {
'dblclick label' : 'edit',
'keypress .edit' : 'updateOnEnter',
'blur .edit' : 'close',
'click .toggle': 'toggleCompleted',
'click .destroy': 'destroy'
},
edit: function(){
this.$el.addClass('editing');
this.input.focus();
},
close: function(){
var value = this.input.val().trim();
if(value) {
this.model.save({title: value});
}
this.$el.removeClass('editing');
},
updateOnEnter: function(e){
if(e.which == 13){
this.close();
}
},
toggleCompleted: function(){
this.model.toggle();
},
destroy: function(){
this.model.destroy();
}
});
// renders the full list of todo items calling TodoView for each one.
app.AppView = Backbone.View.extend({
el: '#todoapp',
initialize: function () {
this.input = this.$('#new-todo');
app.todoList.on('add', this.addAll, this);
app.todoList.on('reset', this.addAll, this);
app.todoList.fetch(); // Loads list from local storage
},
events: {
'keypress #new-todo': 'createTodoOnEnter'
},
createTodoOnEnter: function(e){
if ( e.which !== 13 || !this.input.val().trim() ) { // ENTER_KEY = 13
return;
}
app.todoList.create(this.newAttributes());
this.input.val(''); // clean input box
},
addOne: function(todo){
var view = new app.TodoView({model: todo});
$('#todo-list').append(view.render().el);
},
addAll: function(){
this.$('#todo-list').html(''); // clean the todo list
// filter todo item list
switch(window.filter){
case 'pending':
_.each(app.todoList.remaining(), this.addOne);
break;
case 'completed':
_.each(app.todoList.completed(), this.addOne);
break;
default:
app.todoList.each(this.addOne, this);
break;
}
},
newAttributes: function(){
return {
title: this.input.val().trim(),
completed: false
}
}
});
//--------------
// Routers
//--------------
app.Router = Backbone.Router.extend({
routes: {
'*filter' : 'setFilter'
},
setFilter: function(params) {
console.log('app.router.params = ' + params);
window.filter = params.trim() || '';
app.todoList.trigger('reset');
}
});
//--------------
// Initializers
//--------------
app.router = new app.Router();
Backbone.history.start();
app.appView = new app.AppView();
</script>
</body>
</html>
这条线在做什么:
remaining: function() {
return this.without.apply( this, this.completed() );
}
那是干什么的?
without
来自下划线,但 apply
来自什么?我还在匿名函数的那一行上面放了一个调试器,这是一个错误:
this.apply(this, this.copmleted());
为什么那行不通? apply
是什么?
没有
Backbone Collection's underscore methods
Backbone proxies to Underscore.js to provide 46 iteration functions on
Backbone.Collection.
this.without
与应用于集合本身的 _.without
相同。
关于此的更多 。
应用
apply
是 Function 原型中的一个函数(在 JavaScript 规范中)。它以 context 作为第一个参数(在本例中为 this
)和一个类似数组的对象,指定调用函数时使用的参数。
上下文是函数内this
的值;它是函数执行其逻辑的对象。
this.completed()
returns 一个数组,但是 this.without
需要单独传递每个参数。例如:
this.without(1, 2, 3, 4, 6, 78);
要将 this.completed()
返回的数组展开到参数列表中,可以使用 .apply
:
this.without.apply(this, [completedModel1, completedModel2, /* etc. */]);
这是一个 backbone 教程。这是代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>To-do App in Backbone.js</title>
<!-- ========= -->
<!-- CSS -->
<!-- ========= -->
<style type="text/css">
#todoapp ul {
list-style-type: none; /* Hides bullet points from todo list */
}
#todo-list input.edit {
display: none; /* Hides input box*/
}
#todo-list .editing label {
display: none; /* Hides label text when .editing*/
}
#todo-list .editing input.edit {
display: inline; /* Shows input text box when .editing*/
}
</style>
</head>
<body>
<!-- ========= -->
<!-- Your HTML -->
<!-- ========= -->
<section id="todoapp">
<header id="header">
<h1>Todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus>
<div>
<a href="#/">show all</a> |
<a href="#/pending">show pending</a> |
<a href="#/completed">show completed</a>
</div>
</header>
<section id="main">
<ul id="todo-list"></ul>
</section>
</section>
<div>
<p>Find the tutorial and code in <a href="http://adrianmejia.com/blog/2012/09/11/backbone-dot-js-for-absolute-beginners-getting-started/">here</a></p>
</div>
<!-- Templates -->
<script type="text/template" id="item-template">
<div class="view">
<input class="toggle" type="checkbox" <%= completed ? 'checked' : '' %>>
<label><%- title %></label>
<input class="edit" value="<%- title %>">
<button class="destroy">remove</button>
</div>
</script>
<!-- ========= -->
<!-- Libraries -->
<!-- ========= -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.0/backbone.localStorage-min.js" type="text/javascript"></script>
<!-- =============== -->
<!-- Javascript code -->
<!-- =============== -->
<script type="text/javascript">
'use strict';
var app = {}; // create namespace for our app
//--------------
// Models
//--------------
app.Todo = Backbone.Model.extend({
defaults: {
title: '',
completed: false
},
toggle: function(){
this.save({ completed: !this.get('completed')});
}
});
//--------------
// Collections
//--------------
app.TodoList = Backbone.Collection.extend({
model: app.Todo,
localStorage: new Store("backbone-todo"),
completed: function() {
return this.filter(function( todo ) {
return todo.get('completed');
});
},
remaining: function() {
debugger;
return this.without.apply( this, this.completed() );
}
});
// instance of the Collection
app.todoList = new app.TodoList();
//--------------
// Views
//--------------
// renders individual todo items list (li)
app.TodoView = Backbone.View.extend({
tagName: 'li',
template: _.template($('#item-template').html()),
render: function(){
this.$el.html(this.template(this.model.toJSON()));
this.input = this.$('.edit');
return this; // enable chained calls
},
initialize: function(){
this.model.on('change', this.render, this);
this.model.on('destroy', this.remove, this); // remove: Convenience Backbone's function for removing the view from the DOM.
},
events: {
'dblclick label' : 'edit',
'keypress .edit' : 'updateOnEnter',
'blur .edit' : 'close',
'click .toggle': 'toggleCompleted',
'click .destroy': 'destroy'
},
edit: function(){
this.$el.addClass('editing');
this.input.focus();
},
close: function(){
var value = this.input.val().trim();
if(value) {
this.model.save({title: value});
}
this.$el.removeClass('editing');
},
updateOnEnter: function(e){
if(e.which == 13){
this.close();
}
},
toggleCompleted: function(){
this.model.toggle();
},
destroy: function(){
this.model.destroy();
}
});
// renders the full list of todo items calling TodoView for each one.
app.AppView = Backbone.View.extend({
el: '#todoapp',
initialize: function () {
this.input = this.$('#new-todo');
app.todoList.on('add', this.addAll, this);
app.todoList.on('reset', this.addAll, this);
app.todoList.fetch(); // Loads list from local storage
},
events: {
'keypress #new-todo': 'createTodoOnEnter'
},
createTodoOnEnter: function(e){
if ( e.which !== 13 || !this.input.val().trim() ) { // ENTER_KEY = 13
return;
}
app.todoList.create(this.newAttributes());
this.input.val(''); // clean input box
},
addOne: function(todo){
var view = new app.TodoView({model: todo});
$('#todo-list').append(view.render().el);
},
addAll: function(){
this.$('#todo-list').html(''); // clean the todo list
// filter todo item list
switch(window.filter){
case 'pending':
_.each(app.todoList.remaining(), this.addOne);
break;
case 'completed':
_.each(app.todoList.completed(), this.addOne);
break;
default:
app.todoList.each(this.addOne, this);
break;
}
},
newAttributes: function(){
return {
title: this.input.val().trim(),
completed: false
}
}
});
//--------------
// Routers
//--------------
app.Router = Backbone.Router.extend({
routes: {
'*filter' : 'setFilter'
},
setFilter: function(params) {
console.log('app.router.params = ' + params);
window.filter = params.trim() || '';
app.todoList.trigger('reset');
}
});
//--------------
// Initializers
//--------------
app.router = new app.Router();
Backbone.history.start();
app.appView = new app.AppView();
</script>
</body>
</html>
这条线在做什么:
remaining: function() {
return this.without.apply( this, this.completed() );
}
那是干什么的?
without
来自下划线,但 apply
来自什么?我还在匿名函数的那一行上面放了一个调试器,这是一个错误:
this.apply(this, this.copmleted());
为什么那行不通? apply
是什么?
没有
Backbone Collection's underscore methods
Backbone proxies to Underscore.js to provide 46 iteration functions on Backbone.Collection.
this.without
与应用于集合本身的 _.without
相同。
关于此的更多
应用
apply
是 Function 原型中的一个函数(在 JavaScript 规范中)。它以 context 作为第一个参数(在本例中为 this
)和一个类似数组的对象,指定调用函数时使用的参数。
上下文是函数内this
的值;它是函数执行其逻辑的对象。
this.completed()
returns 一个数组,但是 this.without
需要单独传递每个参数。例如:
this.without(1, 2, 3, 4, 6, 78);
要将 this.completed()
返回的数组展开到参数列表中,可以使用 .apply
:
this.without.apply(this, [completedModel1, completedModel2, /* etc. */]);