js函数中的那些的属性

今天翻看红宝书看到了一些函数中的属性

  1. arguments大家很熟悉,一个类数组对象,包含调用函数时传入的所有参数,这个对象只有以function关键字定义函数才会有。但是arguments里面还有一个callee属性,指向了arguments对象所在函数的指针。书中举了一个例子。
js 复制代码
// 写法1
function factorialA(num) {
    if (num <= 1) {
        return 1
    } else {
        return num * factorial(num - 1)
    }
}

以上代码可以改写成:

js 复制代码
// 写法2
function factorialB(num) {
    if (num <= 1) {
        return 1
    } else {
        //改写成如下,这可以让函数逻辑与函数名解耦
        return num * arguments.callee(num - 1)
    }
}

使用场景: 以下代码trueFactorial被赋值为factorialA,实际将同一个函数的指针保存到另外一个位置,然后factorialA又被重写成一个返回0的函数。此时会发生以下情况:

基于上述写法1:

js 复制代码
    let trueFactorial = factorialA
    factorialA = function () {
        return 0
    }
    console.log(trueFactorial(6)) // 0
    console.log(factorialA(6)) // 0 

基于上述写法2:

js 复制代码
    let trueFactorial = factorialB
    factorialB = function () {
        return 0
    }
    console.log(trueFactorial(6)) // 120
    console.log(factorialB(6)) // 0 
  1. this,在标准函数中引用的是把函数当成方法调用的上下文对象。 定义在全局上下文中的函数sayColor引用了this对象,这个this对象引用哪个对象必须到函数被调用时才能确定。如下面的代码,全局定义的sayColor函数和o.sayColor是同一个函数,只不过执行上下文不同:
js 复制代码
    window.color = 'red';
    let o = {
        color: 'blue'
    }
    function sayColor() {
        console.log(this.color)
    }
    // 全局上下文调用,此时this指向window,this.color === window.color
    sayColor() // 'red'
    o.sayColor = sayColor()
    // this指向o
    o.sayColor() // 'blue'

某些情况下就会有问题,如:

js 复制代码
    window.name = 'window'
    function King() {
        this.name = 'Henry';
        setTimeout(function () { console.log(this.name) }, 1000)
    }
    new King() // 'window'    

发现上述代码的定时器没有指向想要的对象,可以通过箭头函数解决此问题,这是因为箭头函数的this会保留定义该函数时的上下文

js 复制代码
    function King() {
        this.name = 'Henry';
        setTimeout(() => console.log(this.name), 1000)
    }
    new King() // 'Henry'   
  1. caller,这个属性指向的是调用当前函数的函数。 以下代码会显示outer函数的源码
js 复制代码
    function outer() {
        inner()
    }

    function inner() {
        console.log(inner.caller)
    }

    console.log(outer()) // ƒ outer() { inner() }
  1. new.target,ECMAScript中的函数始终可以作为构造函数实例化一个新对象也可以作为普通函数被调用。ES6新增new.target检测函数是否使用new关键字调用。如果普通函数调用new.target的值是undefined,如果是new关键字调用,则new.target将引用被调用的函数。
js 复制代码
    function King() {
        if (!new.target) {
            throw 'King must be instantiated using "new"'
        }
        console.log('King instantiated using "new"')
    }
    new King(); // 'King instantiated using "new"' 
    King(); // 'King must be instantiated using "new"'

这个有啥用呢?我们可以使用new.target定义一个不能被实例化的抽象基类,我们不希望Vehicle被实例化,如下:

js 复制代码
    class Vehicle {
        constructor() {
            if (new.target === Vehicle) {
                throw new Error('Vehicle cannot be directly instantiated')
            }
        }
    }

    class Bus extends Vehicle { }

    new Bus() // 正常
    new Vehicle() // Error:Vehicle cannot be directly instantiated
  1. length和name,length属性保存函数定义的命名参数的个数。如:

    js 复制代码
        function sayName(name) {
            console.log(name)
        }
    
        function sum(num1, num2) {
            return num1 + num2
        }
    
        function sayHi() {
            console.log("hi")
        }
    
        console.log(sayName.length) // 1
        console.log(sum.length) // 2
        console.log(sayHi.length) // 0

    name 属性保存的是 Function 实例的 name 数据属性表示函数在创建时指定的名称,或者如果函数是匿名函数,则名称可以是 anonymous'',如:

    js 复制代码
    const func1 = function () {};
    
    const object = {
      func2: function () {},
    };
    
    console.log(func1.name); // "func1"
    console.log(object.func2.name); // "func2"
    
    //并且函数的name属性是只读的,不能用赋值运算符修改,但可以使用Object.defineProperty()改变。
    function someFunction() {}
    
    someFunction.name = "otherFunction";
    console.log(someFunction.name); // someFunction
相关推荐
excel24 分钟前
HBuilderX 配置 adb.exe + 模拟器端口一体化完整指南
前端
拖拉斯旋风39 分钟前
与 AI 协作的新范式:以文档为中心的开发实践
前端
dualven_in_csdn40 分钟前
【electron】解决CS里的全屏问题
前端·javascript·electron
库克表示43 分钟前
MessageChannel-通信机制
前端
拖拉斯旋风1 小时前
深入理解 Ajax:从原理到实战,附大厂高频面试题
前端·ajax
用户4099322502121 小时前
Vue 3响应式系统的底层机制:Proxy如何实现依赖追踪与自动更新?
前端·ai编程·trae
却尘1 小时前
一个"New Chat"按钮,为什么要重构整个架构?
前端·javascript·next.js
ERIC_s1 小时前
记一次 Next.js + K8s + CDN 缓存导致 RSC 泄漏的排查与修复
前端·react.js·程序员
168清纯女高1 小时前
路由动态Title实现说明(工作问题处理总结)
前端
二川bro2 小时前
第30节:大规模地形渲染与LOD技术
前端·threejs