刨了Function()函数对象的祖坟

第一章:深入了解函数的属性和方法

知识点

  1. 函数也是对象
  2. 对象成员包括属性和方法

1. 函数对象的属性和方法详解

arguments 属性:

  • 属性值: 对象
  • 这个参数,只有函数内部使用,在调用时,才有意义
  • 调用函数的实参列表,是一个类似数组的对象,但不是数组
  • argument[0]..: 访问调用的实参
  • arguments属性:
    • argument.length: 实参数量
    • argument.callee: 被调用的函数体,即自身的引用
  • 示例:
function f(m,n) {
  console.log(arguments)
  console.log(arguments.callee);
  console.log(arguments.length);
  for (var i = 0; i < arguments.length; i += 1) {
      console.log(arguments[i]);
  } 
}

f(1,2,3);

/*
arguments 对象返回内容:
0: 1
1: 2
2: 3
callee: ƒ f(m,n)
length: 3
Symbol(Symbol.iterator): ƒ values()
__proto__: Object

---------------------------------------------------------------------
arguments.callee 返回值:
f(m,n) {
  console.log(arguments)
  console.log(arguments.callee);
  console.log(arguments.length);
  for (var i = 0; i < arguments.length; i += 1) {
      console.log(arguments[i]);
  } 

---------------------------------------------------------------------

arguments.length 返回值: 3

---------------------------------------------------------------------

arguments对象遍历返回值: 
1
2
3

由此可见,形参只是一个占位符罢了,实际参数以arguments对象为准

caller 属性:

  • 属性值: 对象(当前函数调用者的引用)
  • 顶层调用返回: null
  • 示例:
function f() {
  console.log( f.caller );
}

f();    // null

function f1() {
    f()
}
f1() // 返回 f1()函数的引用(体)

length 属性:

  • 返回形参数量(整数)
  • 默认参数,剩余参数不计算在内
  • 示例:
function f(a,b, c=10, ...d) {}
console.log(f.length);  
// 返回2, c=100,...d没有统计在内

name 属性:

  • 返回:当前函数的名称字符串
  • 匿名函数,ES5返回空, ES6正常返回函数引用
  • 示例:
function f1(){}
let f2 = function () {}
console.log(f1.name);   // f1
console.log(f2.name);   // f2(ES6)

prototype 属性

  • 原型属性是函数中最重要的属性之一

  • 原型属性prototype对象2个属性:

  • 任何对象都会有这二个属性
    + constructor: 当前函数的引用
    + __proto__: Object

  • prototype: 指向原型对象的拥有者,即当前函数引用

  • __proto__: 指向原型对象的原型: Object

所有对象归根对底都是内置函数: Object()的实例

function F() {}
console.log(F.prototype);
/* 结果:
constructor: ƒ F()
__proto__: Object
*/

// 等价于
F.prototype = {
    constructor: F(),
    __proto__: Object
}
  • 如果这是一个构造函数,那么这个原型对象是复制到新的实例中

扩展知识:

  • JavaScript是基于原型链继承的
  • 每个实例都会从它的构造函数的原型对象上复制属性到自身
  • 所以,不存在完全空白的对象(除非重写构造函数的原型对象)

constructor 属性:

  • 返回当前函数的构造函数
  • 函数也是对象,所有也有构造器
  • 函数构造就是构造函数: Function
  • 示例:
function f() {}
console.log(f.constructor);  // Function 
  • 为什么是构造函数: Function 呢?
  • 因为所有函数都是Function的实例
  • 即: 函数除了用关键字function创建外,还可以用它

Function(): 参数必须全部是字符串,最后一个是函数体,前都是形参

let sum = new Function('a', 'b', 'return a + b;')
console.log( sum(5, 3) ); // 8

// 与下面函数定义等价: 函数字面量
let sum1 = function (a, b) { return a + b; }
console.log( sum1(5, 3) );  // 8

toString()方法

  • 该方法是函数从它的构造函数原型上继承过来的方法
  • 其实所有对象,都有这个方法,该方法来自: Object()
  • 该方法返回函数的字符串表示
function f(a,b) { return a + b; }
console.log(f.toString());
//"function f(a,b) { return a + b; }"

valueOf()方法

  • 该方法是函数从它的构造函数原型上继承过来的方法
  • 其实所有对象,都有这个方法,该方法来自: Object()
  • 该方法返回函数的值,即函数声明
function f(a,b) { return a + b; }
console.log(f.valueOf());
//function f(a,b) { return a + b; }
// 与toString()相比,仅仅是去掉了一对双引号("...")定界符

apply()call()方法

  • apply()call()用于自定义函数的调用者
  • 二者第一个参数,都是调用函数的对象
  • call(obj, param...): 参数以列表方式传递
  • apply(obj, [param...]): 参数以数组方式传递
function f1(a,b){return a + b;}

// 全局调用
f1(2,3);

// 全局对象是window,以下也是合法调用
window.f1(2,3);  // 5

// this 当前指向全局对象window
this.f1(2,3);   // 5

// call()可人为设置函数调用者,以下调用与上面等效
// 在window对象上调用 f1()
f1.call(window,3,5); // 8

// 在this指向的变量对象上调用 f1()
f1.call(this,3,5);  // 8

// apply()功能与call()一样,仅参数传递方式不同
// call()列表传参, apply()数组传参
f1.apply(window,[3,5]);  // 8

f1.apply(this,[3,5]);  // 8

你可能感兴趣的:(刨了Function()函数对象的祖坟)