变量作用域
作用域指在编写的算法函数中,我们能访问的变量。有本地变量和全局变量两种。
var myVaribale = 'global';
myOtherVaribale = 'global';
function myFunction(){
var myVaribale = 'local';
return myVaribale;
}
function myOtherFunction(){
myOtherVaribale = 'local';
return myOtherVaribale;
}
console.log(myVariable);//'global'
console.log(myFunction());//'local'
console.log(myOtherVaribale);//'global'
console.log(myOtherFunction());//'local'
console.log(myOtherVaribale);//'local'
操作符
编程语言里都需要操作符。在JS里有算数操作符、赋值操作符、比较操作符、逻辑操作符、位操作符、一元操作符和其他操作符。
//算数操作符 //赋值操作符
+ 加法 = 赋值
- 减法 += 加/赋值(x += y) == (x = x + y)
* 乘法 -= 减/赋值(x -= y) == (x = x - y)
/ 除法 *= 乘/赋值(x *= y) == (x = x * y)
% 取余 /= 除/赋值(x /= y) == (x = x / y)
++ 递增 %= 取余/赋值(x %= y) == (x = x % y)
-- 递减
//比较操作符 //逻辑操作符
== 相等 && 与
=== 全等 || 或
!= 不等 ! 非
> 大于
>= 大等于
< 小于
<= 小等于
真值假值
数值类型 转换成布尔值
undefined false
null false
布尔值 true--true,false ---false
数字 0和NaN----false,其他都是true
字符串 空字符串为 false,其他都是true
对象 true
注:new 出来的为对象始终为true (new String('') ---- true)
相等操作符
类型(x) 类型(y) 结果
null undefined true
数字 字符串 x == toNumber(y)
布尔值 任何类型 toNumber(x) == y
字符串或数字 对象 x == toPrimitive(y)
面向对象
创建普通对象有两种方式:
1、var obj = new Object();
2、var obj = {};
创建完成对象:
obj = {
name:{
first:'Gandalf'
}
}
在OOP中,对象是类的实例。一个类定义了对象的特征。我们会创建很多类来表示算法和数据结构。
function Book(title, pages, isbn){
this.title = title;
this.pages = pages;
this.isbn = isbn;
}
实例化这个类:
var book = new Book('title','pag','isbn');
修改对象的属性:
book.title = 'new title';
原型里声明和使用函数:
Book.prototype.printTitle = function(){
console.log(this.title);
};
直接在类的定义里声明函数:
function Book(title, pages, isbn){
this.title = title;
this.pages = pages;
this.isbn = isbn;
this.printIsbn = function(){
console.log(this.isbn);
}
};
在原型的例子里,printTitle方法只会创建一次,在Book类的所有实例中共享。如果在定义类的内部结构时声明,每个类的实例都会有一份该方法的副本。最好在声明公共方法时使用基于原型的方法。
数组
创建斐波那契数列,第一个数字是1,第二个是2,第三项开始,每一项等于前两项之和:
var fibonacci = [];
fibonacci[0] = 1;
fibonacci[1] = 2;
for(var i = 2; i<20;i++){
fibonacci[i] = fibonnacci[i-1] + fibonnacci[i-2];
}
数组方法:
1、array.push:往数组末尾添加任意元素
2、array.unshift:往数组首位添加任意元素
3、array.pop:删除数组最后一位元素,并返回这个元素
4、array.shift:删除数组第一位元素,并返回这个元素
5、array.splice:往数组任意位置删除或添加任意元素
PS: --array.splice(1,3)--- 在数组第二位删除3项元素,并以数组形式返回被删除元 素;
--array.splice(1,0,2,3,4)---往数组的第二位添加2,3,4三项元素,若删除元素为 0,则返回空数组;
6、array.concat:连接2个或更多数组,并返回结果;
7、array.every:对数组中的每一项运行给定函数,直到返回false,如果每一项都返回true,则返回true;
PS:--array.every(function(x){
return (x % 2 == 0)
}) --------返回true 或者 false
8、array.some:该方法和every方法类似,对数组中的每一项运行给定函数,如果任一项返回true,则返回true;
PS:--array.some(function(x){
return (x % 2 == 0)
}) --------返回true 或者 false
9、array.forEach:对数组中的每一项运行给定函数,该方法没有返回值;
10、array.map:对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组;
PS:--var a = [1,2,3,4,5];
a.map(function(x){
return x +1
}) ----------返回数组[2,3,4,5,6],注:a数组不变;
11、array.filter:对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组;
PS:--var a =[1,2,3,4,5];
a.filter(function(x){
return (x % 2 == 0);
}) --------返回数组[2,4],a数组不变
12、array.reduce:该方法可接收一个函数作为参数和一个初始值,第一次调用函数会将初始值作为参数而非数组值,这个函数有四个参数: previousValue、currentValue、index和array。这个函数会返回一个将被叠加到累加器的值,reduce方法停止执行后会返回这个累加器。如果要对一个数组中的所有元素求和,这就很有用;
PS:--function process(previousArray,currentValue){
var nextArray;
if(currentValue >= 1 && currentValue <= 10){
nextArray = previousArray.push(currentValue);
}else{
nextArray = previousArray
}
return nextArray;
}
var numbers = [20,1,-4,6,30,5,8],emptyArray = [];
numbers .reduce(process,emptyArray);--------返回数组[1,6,5,8]
13、array.reverse:反序排列数组,原先数组最后一位元素变成第一位;
14、array.sort:按照字母顺序对数组进行排列,支持传入指定排序方法的函数作为参数
PS: ----var numbers = [2,3,5,7,1,6,8];
numbers.sort(function(a,b){
return a-b
})-----返回numbers数组[1,2,3,5,6,7,8],a-b为升序排列,b-a为降序排列;若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值,做升序排列。
15、array.indexOf:返回与参数匹配的第一个元素的索引,若参数不在数组里则返回-1;
16、array.lastIndexOf:返回与参数匹配的最后一个元素的索引。
17、array.toString:把数组里的所有元素输出为一个字符串;
PS:---var numbers = [1,2,3,4,5];
numbers.toString() ----- 返回字符串'1,2,3,4,5',不改变原数组;
18、array.join:把数组里的所有元素用参数拼接;
PS:---var numbers = [1,2,3,4,5];
numbers.join('-') ---- 返回'1-2-3-4-5',不改变原数组;
推荐资源:
1、http://www.w3schools.com/js/js_arrays.asp;
2、http://www.w3schools.com/js/js_array_methods.asp;
3、Mozilla的数组及其方法的页面
4、数组库:Underscore: http://underscorejs.org/ Lo-Dash: http://lodash.com/
栈
栈是一种遵从后进先出原则的有序集合。新添加的或待删除的元素都保存在栈的末尾,称作栈顶,另一端就叫栈底。在栈里,新元素都靠近栈顶,就元素都接近栈底。
栈的创建
我们创建一个类来表示栈:
function Stack(){};
首先,我们需要一种数据结构来保存栈里的元素。可以选择数组:
var items = [];
接下来,要为我们的栈声明一些方法:
1、push(element(s)):添加一个(或几个)新元素到栈顶。
2、pop():移除栈顶的元素,同时返回被移除的元素。
3、peek():返回栈顶的元素,不对栈做任何修改(这个方法不会移除栈顶的元素,仅仅返回它)。
4、isEmpty():如果栈里没有任何元素就返回true,否则返回false。
5、clear():移除栈里的所有元素。
6、size():返回栈里的元素个数。这个方法和数组的length属性很类似。
首先,我们要实现的第一个方法是push。这个方法往栈里添加新元素,只添加元素到栈顶,也就是栈的末尾。
this.push = function(element){
items.push(element);
};
因为我们使用了数组来保存栈里的元素,所以我们可以使用数组里的push方法来实现。
接着,我们实现第二个方法pop。这个方法主要用来移除栈里的元素。栈遵循后进先出的原则,因此移除的是最后添加进去的元素,所以我们可以使用数组里的pop方法来实现。
this.pop = function(){
return items.pop();
}
只能用push和pop方法添加和删除栈中元素,这样一来,我们的栈自然就遵从了lifo原则。
现在,为我们的类实现一些额外的辅助方法。如果想知道栈里面最后添加的元素是什么,可以用peek方法。
this.peek = function(){
return items[items.length-1];
}
接着要实现的方法是isEmpty,如果栈为空的话就返回true,否则就返回false;
this.isEmpty = function(){
return items.length == 0;
}
类似于数组的length属性,我们也能实现栈的长度方法size;
this.size = function(){
return items.length;
}
最后,我们来实现clear方法,用来移除栈里所有的元素。
this.clear = function(){
items = [];
}
这样栈就实现了,为了检查栈里的内容,我们来实现一个辅助方法,叫print,它会把栈里的元素都输出到控制台。
this.print = function(){
console.log(items.toString());
}
这样,我们就完整创建了栈!
使用栈
现在我们就来实现一个十进制转化成二进制的过程:
function divideBy2(decNumber){
var remStack = new Stack(),rem,binaryString = '';
while(decNumber >0){
rem = Math.floor(decNumber % 2);
remStack.push(rem);
decNumber = Math.floor(decNumber / 2)
}
while(!remStack.isEmpty()){
binaryString += remStack.pop().toString();
}
return binaryString;
}
这样,我们修改下上面的算法,就能把十进制转换成任何进制。
function baseConverter(decNumber,base){
var remStack = new Stack(),rem,baseString='',digits='0123456789ABCDEF';
while(decNumber >0){
rem = Math.floor(decNumber % base);
remStack.push(rem);
decNumber = Math.floor(decNumber / base);
}
while(!remStack.isEmpty()){
baseString += digits[remStack.pop()];
}
return baseString;
}
队列
队列和栈非常类似,但是使用了不同的原则,其是遵从先进先出原则的一组有序的项。队列在尾部添加新元素,并从顶部移除元素,最新添加的元素必须排在队列的末尾。
队列的创建
我们创建一个类来表示队列:
function Queue(){};
首先,我们需要一个用于存储队列中元素的数据结构。我们可以使用数组,就像在上一章Stack类中那样使用:
var items = [];
接下来,我们声明一些队列可用的方法:
1、enqueue(element(s)):向队列尾部添加一个(或多个)新的项。
2、dequeue():移除队列的第一项,并返回被移除的元素。
3、front():返回队列中第一个元素----最先被添加,也将是最先被移除的元素,队列不做任何变动。
4、isEmpty():如果队列中不包含任何元素,返回true,否则返回false。
5、clear():移除队列里的所有算数。
6、size():返回队列包含的元素个数,与数组的length属性类似。
首先要实现的是enqueue方法,这个方法往队列里添加新元素,只添加到队列末尾:
this.enqueue = function(element){
items.push(element);
}
接下来要实现的是dequeue方法,这个方法删除队列里的第一项:
this.dequeue = function(){
return items.shift();
}
只有enqueue方法和dequeue方法可以添加和移除元素,这样就确保了Queue类遵从先进先出原则。
现在,为我们的类实现一些额外的辅助方法,如果想知道队列最前面的项是什么,可以用front方法:
this.front = function(){
return items[0]
}
接着要实现isEmpty方法,如果队列为空返回true,否则就返回false。
this.isEmpty = function(){
return items.length == 0;
}
接着是size方法,来获取队列的长度。
this.size = function(){
return items.length;
}
最后来实现clear方法。
this.clear = function(){
items = [];
}
这样队列就实现了,也可以像Stack类一样增加一个print方法:
this.print = function(){
console.log(items.toString());
}
这样,我们就实现了一个队列!
优先队列
优先队列中,元素的添加和移除是基于优先级的。一个现实的例子就是医院的急诊,要实现优先队列,有两种选项:设置优先级,然后在正确的位置添加元素;或者用入列操作添加元素,然后按照优先级移除它们。
我们创建一个类来表示优先队列:
function PriorityQueue(){
var items = [];
//创建一个队列元素类,在接下来的添加元素方法中会使用到
function QueueElement(element,priority){
this.element = element;
this.priority = priority;
}
};
接下来我们实现enqueue方法,在队列的正确位置添加元素。
this.enqueue = function(element,priority){
var queueElement = new QueueElement(element,priority);
if(this.isEmpty()){//this指向该优先队列,这里直接调用判断队列是否为空的方法
items.push(queueElement);
}else{
var added = false;
for (var i; i
循环队列
循环队列的一个例子就是击鼓传花游戏,在这个游戏里,孩子们围成一个圈,把花尽快的传递给旁边的人。某一时刻花停止,这个时候花在谁手里,谁就退出圆圈结束游戏。重复这个过程,直到只剩一个孩子(胜者)。
下面,我们实现一个模拟的击鼓传花游戏:
function hotPotato (nameList,num){
var queue = newQueue();
for(var i=0;i1){
for(var i=0;i