我的JS笔记 -- 函数

作者: 骷髅不会笑丶 | 来源:发表于2017-12-13 21:59 被阅读0次

函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块,在JS中定义函数的方式有两种:函数声明和函数表达式。

区分函数声明和表达式最简单的方法是看function关键字出现在声明中的位置(不仅仅是一行代码, 而是整个声明中的位置)。如果function是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式。

// 函数声明
function f1() {
    //
}

// 函数表达式
var f2 = function () {
    //
}

// 函数表达式
(function () {
    //
})()

函数声明会提升,但函数表达式不会。声明提升在执行上下文

function f() {
    console.log(1);
}
f(); // 1
var f = function () {
    console.log(2);
}
f(); // 2

因为函数声明会提升,所以不能非函数的代码块中声明函数,比如if。

// 下面代码的原始意图是不声明函数f,但是由于f的提升,导致if语句无效,所以上面的代码不会报错
if (false) {
    // 这样声明因为if不是块级作用域,那么函数会提升,不论if如何判断f()都会生效
    function f1() {
        console.log(1);
    } 
}
f1(); // 1
    

// 要达到在条件语句中定义函数的目的,只有使用函数表达式
if (false) {
    var f2 = function () {
        console.log(2);
    }
}
f2(); // TypeError: f2 is not a function

但我在测试时发现新版火狐、Chrome、IE11都不会在if中提升函数声明,但IE11以下版本会,所以为避免出错,尽量在if等非函数代码块中使用函数表达式。

函数传递参数

JS中所有函数的参数都是按值传递的。

var a = 1;
function f1(arg) {
    arg = 2;
    console.log(arg); //2,参数如果是基本类型是按值传递,传递的是参数的副本,操作不影响原变量
}
f1(a);
console.log(a); // 1

var obj = {
    a: 1
};
function f2(arg) {
    arg.value = 2;
    console.log(arg.value); //2,传递对象的时候,传递对象的引用的副本,改变参数会改变原参数
}
f2(obj);
console.log(obj.a) // 2
    
var obj2 = {
    value: 1
};
function f3(arg) {
    arg = { // 函数内部重写参数,这下变量引用的就是一个局部变量
        a: 2
    };
    console.log(arg.a); //2,传递引用参数副本,但是又重新给参数赋值,切断原来的引用,所以原有引用为改变
}
f3(obj2);
console.log(obj2.a) // 1

函数属性

函数属性包括:length和prototype

length,函数的length属性是只读属性,函数定义时的形参个数即通常也是函数调用时期望传入函数的参数个数。

function add(a, b) {
    return a + b;
}
add.length // 2,函数声明时形参长度

prototype,每个函数都包含一个prototype属性,这个属性是指向一个对象的引用,这个对象称为“原型对象”。每个函数都包含不同的原型对象。当函数用做构造函数时,新创建的对象会从原型对象上继承属性。

函数内部属性:arguments和this

arguments,arguments是一个类数组对象,包含传入函数的所有参数,arguments的主要用途是保存函数参数。

function add(a, b) {
    return arguments[0] + arguments[1];
}
add(1, 2); // 3

this,this引用的是函数据以执行的环境对象,关于this请点这里this

var a = {
    name: 'a',
    sayName: function () {
        console.log(this.name);
    }
};
a.sayName(); // 'a'

函数方法

每个函数都包含两个非继承而来的方法:apply()和call()。这两个方法的用途都是在特定的域中调用函数,其真正强大之处在于能够扩充函数赖以运行的作用域,ES5又新增bind()方法。

关于apply、call和bind请点这里this

因为函数也是对象,所以函数也有toString()方法,返回函数的字符串形式。

匿名函数

函数声明必须要有标识符名称,但函数表达式可以不写标识符,这样的函数称为匿名函数。

// 匿名函数赋值给变量
var f = function () {
    //
}

// 匿名函数自执行,自执行后内部声明的局部变量和函数会被销毁
(function () {
    //
})()    

// 匿名函数不会自执行,会报错,这是因为这是一个函数声明,函数声明后边不能跟圆括号,函数表达式后边可以跟圆括号
function () {
    // 
}()

更多文章在 这里 ,觉得不错希望点个 star

相关文章

  • 我的JS笔记 -- 函数

    函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块,在JS中定义函数的方式有两种:函数声明和函数表达式。 ...

  • js中的arguments对象

    《JavaScript高级程序设计》读书笔记 js中函数的参数与别的语言的参数有些不同。js中的函数不介意传递进来...

  • JavaScript 05 函数

    js函数的概念和作用,js函数的定义,js函数的调用,js事件驱动的概念,js函数的实参和形参,js的作用域,js...

  • jQuery 中的 Deferred 和 Promises

    忘记这是在哪里做的笔记了。。。 js里异步函数大概有I/O函数(ajax、postMessage、请load、sc...

  • JS笔记11:JS函数

    1、函数声明与调用 2、形参 VS 实参 3、函数返回与自调用 4、函数作为参数 参考 1、js中函数声明的三种方...

  • javascript 笔记03(创建对象/原型模式/js 继承/

    js 笔记3 接笔记2 13.创建对象 工厂模式 构造函数模式 以这种方式调用构造函数实际上会经历以下 4 个步骤...

  • js 深入

    * js语法* js的动态函数和匿名函数* js动态函数Functionnew Function();* 匿名函数...

  • 函数式编程小思考4.2 笔记

    函数式编程小思考4 笔记JS函数式编程指南Data.Task 函子 源码 补充两个内容 用得到的curry函数 文...

  • JavaScript作用域学习笔记

    @(JS技巧)[JavaScript, 作用域] JavaScript作用域学习笔记 概念: 作用域就是变量与函数...

  • JS—匿名函数与命名函数

    链接,我之前做的两篇笔记js变量作用域,里面提到定义函数的不同方式,导致的变量声明提升问题。还有这篇js特殊的对象...

网友评论

    本文标题:我的JS笔记 -- 函数

    本文链接:https://www.haomeiwen.com/subject/upttwxtx.html