笔记:《JavaScript学习指南》-第6章函数

第6章 函数
函数是一组语句的集合,它是一个独立运行的程序单元。
每个函数都有一个函数体,它是构成该函数的一组语句集合。
function sayHello(){
    //这是函数体;从一个左花括号开始,到右花括号结束
}

6.1 返回值
函数调用是一种表达式。
在函数体中,return 关键字会立即结束函数并且返回一个特定值,这就是函数调用产生的值。
如果没有明确指定 return 语句,返回值会是 undefined。

6.2 引用调用
函数是一个对象,可以被传递和赋值。
在函数名后添加圆括号,JavaScript就会调用函数并执行函数体,最后返回结果。如果没有圆括号,就只是在引用函数。
可以把函数赋值给一个变量或对象的属性,或把函数添加到数组里。
function getGreeting(){
    return "hello world";
}

//函数赋值给变量
const f = getGreeting;

//函数添加到对象的属性里
const o = {};
o.f = getGreeting;
o.f();

//函数添加到数组里
const arr = [1, 2, 3];
arr[1] = getGreeting;
arr[1]();

6.3 函数参数
参数是指那些在函数调用结束后就不再存在的变量。
参数只存在于函数内部,即使它们在函数外有相同的名字。

6.3.1 参数会让函数有所区别吗
不会,可以使用任意多个参数去调用任何一个函数。如果调用时没有传入参数,函数就会接收到一个为undefined的参数。
function f(x){
    return `the ${x}`;
}
f();    //the undefined

6.3.2 解构参数
把一个对象解构到不同的变量中:
//传入的对象属性名要与参数属性名匹配,否则属性会接受一个undefined值
function getSentence({subject,verb,object}){
    return `${subject} ${verb} ${object}`;
}
const o = {
    subject: "I",
    verb: "love",
    object: "JavaScript"
};

getSentence(o);    // I love JavaScript

解构一个数组:
function getSentence([subject ,verb ,object]){
    return `${subject} ${verb} ${object}` ;
}

const arr = ["I" , "love" , "JavaScript"] ;

getSentence() ;

使用展开操作符( ... )来收集任何多出来的参数:
function addPrefix(prefix, ...words){
    const prefixedWords = [];
    for(let i=0; i<words.length; i++){
        prefixedWords[i] = prefix + words[i];
    }
    return prefixedWords;
}

addPrefix("con","verse", "vex");    // ["converse", "convex"]

6.3.3  默认参数 
ES6新特性。
如果没有给参数传值,它的值将会是undefined。默认值则可以给这些参数指定其他的默认值。
function f(a, b = "default", c= 3){
    return `${a} - ${b} - ${c}`;
}

f(5, 6, 7);    //5 - 6 - 7
f(5, 6);    //5 - 6 - 3
f(5);    //5 - default - 3
f();    //undefined - default -3

6.4 函数作为对象属性
当函数作为对象的属性时,通常称为方法。
const person = {
    name: "liang",
    say: function(){
        return "Hi";
    }
}

//或者使用ES6新的快捷语法
const person = {
    name: "liang",
    say(){return "Hi";}
}

6.5 this 关键字
在函数体中,有一个特殊的只读字段 this,通常与面向对象编程一起出现。
this 关键字通常关联那些作为对象属性的函数。
当方法被调用时,this 关键字的值就是被调用的对象:
const person = {
    name: "liang",
    speak(){
        return `My name is ${this.name}`;
    }
}

person.speak();

const say = person.speak;
say();    //My name is
如何绑定 this 是由方法如何被调用来决定的,而非函数定义所决定的。在这里,this 绑定到 person 上并不是因为 speak 是 person 的属性,而是因为它直接由 person 调用( person.speak )。say调用时,由于JavaScript并不知道原始函数是指 person 中定义的,所以this 将会绑上undefined。

const person = {
    name: "liang",
    greetBackwards: function(){
        function getReverseName(){
            let nameBackwards = '';
            for(let i=this.name.length-1; i>=0; i--){
                nameBackwards += this.name[i];
            }

            return nameBackwards;
        }

        return `${getReverseName()} si eman ym, olleH`;
    },
};

person.greetBackwards();    // " si eman ym, olleH"
当调用person.greetBackwards()时,JavaScript像预期那样给this绑定了值。然而,在greetBackwards中调用 getReverseName 函数时,this 却绑到其他地方。
把this 赋值给另一个变量来解决(也可以使用箭头函数解决):
const person = {
    name: "liang",
    greetBackwards: function(){
         const self = this;
        function getReverseName(){
            let nameBackwards = '';
            for(let i= self.name.length-1; i>=0; i--){
                nameBackwards += self.name[i];
            }

            return nameBackwards;
        }

        return `${getReverseName()} si eman ym, olleH`;
    },
};


person.greetBackwards();    // "gnail si eman ym, olleH"


6.6 函数表达式和匿名函数
//函数声明
function f(){
    //...
}

//函数表达式
const f = function(){
    //...
};
函数表达式创建了一个匿名函数并把它赋给一个变量。匿名函数可以作为其他函数或方法的参数,还可以用来创建对象的函数属性。

6.7 箭头符号
ES6新语法。
箭头符号可以减少敲击function 这个单词和花括号的次数。
如果函数只有一个参数,则可以省略花括号。
如果函数体是一个单独表达式,则可以省略花括号和返回语句。
const f1 = function(){ return "hello!";}
//等效于
const f1 = () => "hello!";

const f2 = function(name){ return `hello,${name}!`;}
//等效于
const f2 = name =>`hello,${name}!`;

const f3 = function(a,b){ return a + b;}
//等效于
const f3 = (a,b) => a+b;

箭头函数跟普通函数之间的主要区别是:this 是跟语句绑定起来的,就像其他变量一样。
通过箭头函数,可以在函数体中使用 this:
const person = {
    name: "liang",
    greetBackwards: function(){
         const getReverseName = () => {
            let nameBackwards = '';
            for(let i=this.name.length-1; i >= 0; i--){
                nameBackwards += this.name[i];
            }

            return nameBackwards;
        };

        return `${getReverseName()} si eman ym, olleH`;
    }
};

person.greetBackwards();    // "gnail si eman ym, olleH"

箭头函数不能当做对象构造器,同时,指定的参数变量在箭头函数中也不生效。

6.8 调用、请求和绑定
call() 方法
call() 方法使用指定的this 来调用函数。
const bruce = { name: "Bruce"};
const madeline = { name: "Madeline"};

function greet(){
     return `Hello, I'm ${this.name}!`;
}

greet();    // "Hello, I'm !"
greet.call(bruce);    // "Hello, I'm Bruce!"
greet.call(madeline);    // "Hello, I'm madeline!"
call() 方法第一个参数表示要传入this的的对象,剩下的参数则变成了要调用的函数的实参。
const bruce = { name: "Bruce"};

function update(birthYear, occupation){
    this.birthYear = birthYear;
    this.occupation = occupation;
}

update.call(bruce, 1949,"singer");
bruce;    // {name: "Bruce", birthYear: 1949, occupation: "singer"}

apply() 方法
除了处理函数参数的方式不同,apply 与 call 基本是一致的。
apply 以数组的方式获取参数:
//...接上例...

update.apply(bruce,[1933,"actor"]);
bruce;    //{name: "Bruce", birthYear: 1933, occupation: "actor"}

bind() 方法
bind() 可以给一个函数永久地绑定 this 值。
//...接前例...

const updateBruce = update.bind(bruce);

updateBruce(1904,"actor");
bruce;    //{name: "Bruce", birthYear: 1904, occupation:"actor"}

updateBruce.call(madeline,1274,"king");
bruce;    // {name: "Bruce", birthYear:1274, occupation:"king"}
风险:使用bind后,函数不能再有效的使用call、apply,bind也不能再次使用。
调用bind时也可以传参数。传入的参数不能再修改。

猜你喜欢

转载自blog.csdn.net/kjhz_liang/article/details/80525903
今日推荐