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
相关推荐
前端Hardy21 分钟前
HTML&CSS:3D图片切换效果
前端·javascript
spionbo42 分钟前
Vue 表情包输入组件实现代码及完整开发流程解析
前端·javascript·面试
全宝43 分钟前
✏️Canvas实现环形文字
前端·javascript·canvas
lyc23333343 分钟前
鸿蒙Core File Kit:极简文件管理指南📁
前端
我这里是好的呀43 分钟前
全栈开发个人博客12.嵌套评论设计
前端·全栈
我这里是好的呀44 分钟前
全栈开发个人博客13.AI聊天设计
前端·全栈
金金金__1 小时前
Element-Plus:popconfirm与tooltip一起使用不生效?
前端·vue.js·element
lyc2333331 小时前
小L带你看鸿蒙应用升级的数据迁移适配📱
前端
用户26812851066691 小时前
react-pdf(pdfjs-dist)如何兼容老浏览器(chrome 49)
前端