定义和调用函数
函数定义
//方法一:函数表达式
//函数也是值,可以把函数类型值赋给变量,cube相当于函数名
var cube = function(x){
return x*x*x);
};
//方法二:函数声明
function cube(x){
return x*x*x;
};
//调用
alert(cube(2)); //方法一方法二的函数均可用此方式调用
函数声明方式可以在定义之前被调用,函数表达式则不行
注:如果一个函数完成了其主体的执行,却没有执行任何return语句,它会返回undefined。
将对象引用作为参数传递
无返回值(方法)
var upperCase = function (a){
for(var i=0;i<a.length;i += 1){
a[i] = a[i].toUpperCase();
}
};
//测试结果
upperCase([]) //undefined
upperCase(["hello","","world"]) //undefined
var dog = ["hello","world"]
upperCase(dog) //undefined
dog //["HELLO","WORLD"]
根据上述代码可知,upperCase没有返回值,但是,它修改了传递给它的对象的属性
有返回值(函数)
var upperCase = function(a){
var result = [];
for(var i=0;i<a.length;i+=1){
result.push(a[i].toUpperCase());
}
return result;
};
//测试结果
upperCase([]) //[]
upperCase(["hello","","world"]) //["HELLO","","WORLD"]
var dog = ["hello","world"]
upperCase(dog) //["HELLO","WORLD"]
dog //["hello","world"]
自调用函数
如果表达式后紧跟(),则会自动调用。
(function () {
var x = "Hello!!"; // 我将调用自己
})(); //最外层的括号说明它是一个表达式
注:不能调用声明的函数
作为对象的函数
函数的属性
function plus1(value) {
if (plus1.invocations == undefined) {
plus1.invocations = 0;
}
plus1.invocations++;
return value + 1;
}
上例中invocation代表函数被调用的次数,相当于面向对象程序设计中的静态属性。
函数的prototype属性
每个对象都有prototype属性,prototype属性用于向类的构造器中加入新的属性
function Rectangle(width, height) {
this.width = width;
this.height = height;
}
Rectangle.prototype.area = function() {
return this.width*this.height;
}
Rectangle.prototype.description="hello";
作为属性的函数
let operson = {
firstName: "John",
lastName : "Doe",
id : 5566,
fullName : function() {
return this.firstName + " " + this.lastName; ////this指的是当前对象,即o
}
};
注:使用this表达式的函数属性称为方法,上例中fullName就是operson的方法
方法
let o = {count: 0};
o.increment=function(amount){
if(amount==undefined){
amount=1;
}
this.count+=amount;
return this.count;
};
//Method invocation:
o.increment();//returns 1
o.increment(3);//returns 4
this
方法中的this指向当前对象,方法之外的this指全局变量。(不建议在方法外使用this)
let o = {oldProp: 'this is an old property'};
o.aMethod = function() {
this.newProp = "this is a new property";
return Object.keys(this); // will contain 'newProp'
};
o.aMethod(); // will return ['oldProp','aMethod','newProp']
构造器(类)
function Rectangle(width, height) {
this.width = width;
this.height = height;
this.area = function() { return this.width*this.height; } //此种定义方式有严重缺陷
}
var r = new Rectangle(26, 14);
r.constructor.name == 'Rectangle'
console.log(r)
在构造器里出现的函数叫做构造函数,上例中area()是Rectangle的构造函数,但是此种定义方式有严重缺陷,在每创建一个Rectangle对象时,也创建了计算面积的方法,会浪费大量内存来保存面积的冗余副本,此问题在javascript可以用prototype解决
function Rectangle(width,height){
this.width = width;
this.height = height;
}
Rectangle.prototype.area = function(width,height){
return this.width * this.height;
}
var r = new Rectangle(26, 14);
r.constructor.name == 'Rectangle'
console.log(r)
继承
通过prototype属性继承
function Shape(str){ this.str=str; }
Shape.prototype.sdescription="Shape"
function Rectangle(width, height) {
this.width = width;
this.height = height;
}
Rectangle.prototype = new Shape("shape"); //Rectangle继承了Shape
var r=new Rectangle();
多态
var shape = function (){};
shape.prototype.draw = function(){
return "i am generic shape";
}
//circle
var circle = function(){}
circle.prototype = Object.create(shape.prototype);
circle.prototype.draw= function(){return "i am a circle";}
//triangle
var triangle = function (){}
triangle.prototype = Object.create(shape.prototype);
triangle.prototype.draw= function(size){
return "this is triangle";
}
var shapes = [new shape(), new circle(), new triangle(23)];
shapes.forEach (function (shapeList){
console.log(shapeList.draw());
});
作用域
use strict
use strict是严格模式,在此模式下不能使用未声明的变量
<script>
"use strict";
if(foo) //error,未声明
alert("happy");
else
y = 3.14;//error,未声明
alert("sad");
</script>
let
let的作用域范围是一个代码块{},{}外不能访问
var x = 10;
// Here x is 10
{
var x = 2;
// Here x is 2
}/
/ Here x is 2
var x = 10;
// Here x is 10
{
let x = 2;
// Here x is 2
}/
/ Here x is 10
const
const 用于声明一个或多个常量,声明时必须进行初始化,且初始化后值不可再修改,const定义的变量并非常量,并非不可变,它定义了一个常量引用一个值。使用const 定义的对象或者数组,其实是可变的。下面的代码并不会报错:
// You can create a constant array:
const cars = ["Saab", "Volvo", "BMW"];
// You can change an element:
cars[0] = "Toyota";
// You can add an element:
cars.push("Audi");
但是不能对常量对象重新赋值
const car = {type:"Fiat", model:"500", color:"white"};
car = {type:"Volvo", model:"EX60", color:"red"}; // 错误
头等函数(first-class function)
- 将函数赋值给变量或将它们存储在变量中,数据结构——函数表达式
- 将函数作为参数传递给其他函数
- 将函数作为其他函数的值返回
var aFuncVar = function (x) { console.log('Called with', x); return x+1; }; function myFunc(routine) { // passed as a param console.log('Called with', routine.toString()); var retVal = routine(10); //var retVal=routine; console.log('retVal', retVal); return retVal; } myFunc(aFuncVar);
//运行结果 Called with function (x) { console.log('Called with', x); return x+1; } Called with 10 retVal 11 11
箭头函数
创建函数的一种更简单的方法
let 函数名= (参数)=>表达式
//箭头函数
let sum = (a,b)=>a+b;
//函数表达式
let sum = function(a,b){
return a+b;
};
alert(sum(1,2)); //3
正则表达式
正则表达式简介
- 正则表达式是组成搜索模式的字符序列。javascript的正则表达式以斜线(/…/)界定。
- 对于正则表达式用test方法,会返回true\false,说明一个正则表达式是否与一个字符串匹配
- 对于字符串应用search方法,将会返回字符串中每一个匹配的位置(如果不匹配则返回-1)
/^Once/ //匹配以Once开头的字符串 /ss$/ //匹配以ss结尾的字符串 /go*gle/ //表示o可以为0个或多个,包括ggle、gogle、google等
捕获
字符串match方法和正则表达式exec方法,捕获字符串中与正则表达式匹配的部分
数量词
- a?匹配零个或一个a
- a*匹配零个或多个a
- a+匹配一个或多个a
这些数量词会匹配尽可能多的字符,如果要匹配较少的字符,应当使用??、* ?、+?"aaaah".match(/a+/) //aaaa "aaaah".match(/a+?/) //a "aaaah".match(/a*/) //aaaa "aaaah".match(/a*?/) //"" "aaaah".match(/a?/) //a "aaaah".match(/a??/) //""
元字符
- \d 寻找一个数据
- \s 寻找一个空白字符
- \b 在开始或结尾找到一个匹配项
'XXX abbbbbbc'.search(/ab+c/); // Returns 4 (position of 'a') 'XXX ac'.search(/ab+c/); // Returns -1, no match 'XXX ac'.search(/ab*c/); // Returns 4 '12e34'.search(/[^\d]/); // Returns 2 'foo: bar;'.search(/...\s*:\s*...\s*;/); // Returns 0
正则表达式修饰符
- i 忽略大小写
- g 全局
- m 多行
/HALT/.test(str); // 如果str里有HALT的子字符串,则返回true /halt/i.test(str); // 同上但忽略大小写 /[Hh]alt [A-Z]/.test(str); // [Hh]表示开头为H、h [A-Z]表示26个大写字母中的一个 eg.halt A \ Halt B
函数式编程
将函数作为参数传递
var anArr = [45, 4, 9, 16, 25];
function filterFunc(value){
return value <45;
}
function mapFunc(value,ind){
return value*ind;
}
function reduceFunc(total,value){
return total+value;
}
anArr.filter(filterFunc).map(mapFunc).reduce(reduceFunc);
//执行filter后:[4,9,16,25]
//执行map后:[0,9,32,75]
//执行reduce后:116
注:filter()\map()\reduce()方法使用方法请参考此博客的javascript1
上述编程可以写为
anArr.filter(value=>value<45).map((value,ind)=>value*ind).reduce((total,value)=>total+value);
闭包
var globalVar = 1;
function localFunc(argVar) {
var localVar = 0;
function embedFunc() {
return ++localVar + argVar + globalVar;
}
return embedFunc;
}
var myFunc = localFunc(10); //返回embedFunc函数
myFunc();// 直接调用embedFunc函数,即localVar =0 不再执行,只执行embedFunc函数