插件窝 干货文章 浅谈JavaScript的对象类型之function

浅谈JavaScript的对象类型之function

class 函数 div pre 766    来源:    2024-10-17

一、Function

定义函数

function 函数名(参数) {
    // 函数体
    return 结果;
}

例如:

function add(a, b) {
    return a + b;
}

调用函数

函数名(实参);

例如:

add(null, 2); // 返回 3

js中的函数调用特点,对参数的类型和个数都没有限制,例如:

add('a', 'b');  // 返回 ab
add(null, 5, 6);   // 返回 9, 第三个参数没有被用到, 不会报错
add(1);         // 返回 NaN, 这时 b 没有定义是 undefined, undefined 做数学运算结果就是 NaN

默认参数

java中(spring)要实现默认参数的效果

@RestController 
public class MyController {
    @RequestMapping("/page")
    @ResponseBody
    public void page(
        @RequestParam(defaultValue="1") int page, 
        @RequestParam(defaultValue="10") int size
    ){
        // ...
    }
}

js实现的效果

function pagination(page = 1, size = 10) {
    console.log(page, size);
}

匿名函数

语法:

(function (参数) {
    // 函数体
    return 结果;
})

例如:

(function(a,b){
    return a + b;
})

第一种场景:定义完毕后立刻调用

(function(a,b){
    return a + b;
})(null,2)

第二种场景:作为其他对象的方法,例如:

页面有元素:

<p id="p1">点我啊</p>

此元素有一个onclick方法,会在鼠标单击这个元素后被执行,onclick方法刚开始是null,需要赋值后才能使用

document.getElementById("p1").onclick = (function(){
    console.log("鼠标单击了...");
});

箭头函数

(参数) => {
    // 函数体
    return 结果;
}
  • 如果没有参数,() 还是要保留
  • 如果只有一个参数,() 可以省略
  • 如果函数体内只有一行代码,{} 可以省略
  • 如果这一行代码就是结果,return 可以省略

例如:

document.getElementById("p1").onclick = () =>  console.log("aa");

二、函数是对象

1、可以参与赋值,例如,匿名函数也能参与赋值

function abc() {
    console.log("bb");
}
document.getElementById("p1").onclick = abc;

2、有属性、有方法,执行console.dir(abc),输出结果如下:

ƒ abc()
    arguments: null
    caller: null
    length: 0
    name: "abc"
    ➡prototype: {constructor: ƒ}
    [[FunctionLocation]]: VM1962:1
    ➡[[Prototype]]: ƒ ()
    ➡[[Scopes]]: Scopes[1]

其中带有 f 标记的是方法,不带的是属性

带有 ➡ 符号的可以继续展开,限于篇幅省略了

带有 [[ ]] 的是内置属性,不能访问,只能查看

相对重要的是 [[Prototype]][[Scopes]] 会在后面继承和作用域时讲到

3、可作为方法参数

function a() {
    console.log('a')
}
function b(fn) {          // fn 将来可以是一个函数对象
    console.log('b')
    fn();                 // 调用函数对象
}
b(a)

4、可作为方法返回值

function c() {
    console.log("c");
    function d() {
        console.log("d");
    }
    return d;
}
c()()

三、函数作用域

函数可以嵌套(js代码很常见,只是嵌套形式很多时匿名函数,箭头函数)

function a() {
    function b() {        
    }
}

例如:

function c() {
    var z = 30;
}
var x = 10;
function a() {
    var y = 20;
    function b() {
        // 看这里
        console.log(x, y);
    }
    b();
}
a();
  • 以函数为分界线划定作用域,所有函数之外是全局作用域
  • 查找变量时,由内向外查找
    • 在内层作用域找到变量,就会停止查找,不会再找外层
    • 所有作用域都找不到变量,报错
  • 作用域本质上是函数对象的属性,可以通过 console.dir 来查看调试

四、闭包

var x = 10;
function a() {
    var y = 20;
    function b() {
        console.log(x,y);
    }
    return b;
}
a()();  // 在外面执行了 b
  • 函数定义时,它的作用域已经确定好了,因此无论函数将来去了哪,都能从它的作用域中找到当时那些变量
  • 别被概念忽悠了,闭包就是指函数能够访问自己的作用域中变量

五、let、var与作用域

如果函数外层引用的是let变量,那么外层普遍的{}也会作为作用于边界,最外层的let也占一个script作用域

let x = 10; 
if(true) {
    let y = 20;
    function b() {
        console.log(x,y);
    }
    console.dir(b);
}

如果函数外层引用的是var变量,外层普遍的{}不会视为边界

var x = 10; 
if(true) {
    var y = 20;
    function b() {
        console.log(x,y);
    }
    console.dir(b);
}

如果var变量出现了重名,则他俩会被视为同一作用域中的同一变量

var e = 10; 
if(true) {
    var e = 20;
    console.log(e); // 打印 20
}
console.log(e);     // 因为是同一个变量,还是打印 20

如果是let,则视为两个作用域中的两个变量

let e = 10; 
if(true) {
    let e = 20; 
    console.log(e); // 打印 20
}
console.log(e);     // 打印 10

要想里面的e和外面的e能区分开来,最简单的办法是改成let,或者用函数来界定作用域范围

var e = 10; 
if(true) {
    function b() {
        var e = 20;
        console.log(e);
    }
    b();
}
console.log(e);

到此这篇关于浅谈JavaScript的对象类型之function的文章就介绍到这了,更多相关JavaScript 对象类型function内容请搜索插件窝以前的文章或继续浏览下面的相关文章希望大家以后多多支持插件窝!