javascript(2)

定义和调用函数

函数定义

//方法一:函数表达式
//函数也是值,可以把函数类型值赋给变量,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函数

   转载规则


《javascript(2)》 fightingtree 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录