JavaScript笔记(二):函数只是一种对象

上一篇随笔提到JS中有两种数据类型:原始类型和对象类型,但是我们还没有提到函数。实际上函数也是一种对象,准确地说函数应该叫做函数对象。下面从对象开始说起。

1. 对象和函数

最简单的对象,是这样的:

var obj = {};

我们创建了一个空对象。说它空是因为它没有任何自定义属性,但是实际上它还是有一些默认属性的,这些属性是从它的原型对象继承来的,比如constructor、toString和valueOf等。除此之外,ECMA-262中还定义了对象的一些内置属性,这些属性对JS语言来说是不可见的,也就是说跟我们的编程无关。但是简单地了解一下这些内置属性,对我们深入理解对象的内部机制是有益的。这些属性包括:[[Prototype]]、[[Extensible]]、[[Get]]、[[Put]]、[[HasProperty]]和[[Delete]]等,具体的含义在此不提,只需要知道,只要是对象,一定具有这些属性。

接下来,我们说一下函数。我们经常听人说“函数是JS中的一等公民,函数可以做参数,可以做返回值”。其实原因很简单,函数也是一种对象,是一种特殊的对象。它只是比普通的对象多了一些特殊的东西,所以看起来跟普通对象有所不同。那么,函数与普通对象比有哪些不同呢?

(1) 从语言规范或者说从JS引擎的角度来看,函数除了前面提到的那些内置属性外,还多了一些内置属性,包括:

  • [[Code]]:函数的代码,即函数体里面的那些语句。
  • [[FormalParameters]]:函数的形参列表。
  • [[Scope]]:词法环境(Lexical Environment),它确定了函数执行时所处的环境。这个东西很重要,跟我们经常听说的作用域链闭包有关系。
  • [[Call]]:执行代码,即在调用此函数时执行的动作。
  • [[Construct]]:构造一个新的对象的动作。拥有这个内置属性的函数被称为构造函数,通过new操作符可以用它来产生新的对象。
  • [[HasInstance]]:用来检测一个对象是否是此函数构造的。

(2) 由于函数是一种特殊的以及非常重要的对象,所以JS语言专门提供了特殊的语法来创建函数,即

// 函数声明
function sayHello() {
    console.log(‘Hello‘);
}

// 函数表达式
var sayHello = function () {
    console.log(‘Hello‘);
}

当然,也可以用类似于创建普通对象的方式(即new+构造函数)来创建函数,即

var sayHello = new Function("console.log(‘Hello‘);");

是不是跟普通对象的方式很像啊:

var data = new Date(‘2015/09/10‘);

显然Function是一个非常特殊的构造函数,因为一般的构造函数只能创建普通对象,但是Function能创建一个函数对象。

(3) 函数是可调用的。我们通过函数调用表达式来调用一个函数,从而完成实现某种特定的功能,例如:

function add(x, y) {
    return x + y;
}

var z = add(3, 4);
console.log(z); // 输出5

这也是我们使用函数最常见的目的。

2. 构造函数

其实上面已经顺带把构造函数也讲了。构造函数是指可以利用 new 操作符来创建对象的函数,这个过程是通过内置属性[[Construct]]实现的。比如Object就是一个构造函数:

var obj = new Object();

实际上,我们在程序里使用函数声明、函数表达式或Function创建出来的函数都是即使普通函数也是构造函数。它们既可以被调用以得到返回值或产生某种效果,也可以用new操作符来创建对象。但是从本质上讲构造函数比普通函数要更特殊一些。

另外为了进行区分,在命名时,前者通常首字母小写,后者通常首字母大写。举一个构造函数的例子:

function Person(name, age) {
    this.name = name;
    this.age = age;
}
时间: 2024-08-04 10:25:56

JavaScript笔记(二):函数只是一种对象的相关文章

JavaScript中的函数的两种定义方式

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript"> /*I总结: 1.函数名可以做变量使用,可以赋值,可以传值 2.函数名当参数,传递给另一个函数 */ //==================js中函

python学习笔记(二) - 函数

一. 调用函数 python内置了一些数据类型转换函数,比如int()函数可以把其他数据类型转换为整形 >>> int('123') 123 >>> int(12.34) 12 >>> float('12.34') 12.34 >>> str(1.23) '1.23' >>> unicode(100) u'100' >>> bool(1) True >>> bool('') Fal

JavaScript笔记二:变量、作用域和内存

1.基本类型和引用类型 基本类型:简单的数据段 引用类型:可能由多个值构成的对象,只能给引用类型添加属性 当复制他们的值时,基本类型实际上是又开辟了独立的空间存储值,而引用类型则是创建了指针,他们关联到同一个对象 2.执行环境和作用域 延长作用域链,没有块级作用域 3.确定一个值是哪种基本类型可以使用typeof操作符,而确定一个值是哪种引用类型可以使用instanceof操作符. 4.所有变量(基本和引用)都存在一个执行环境当中,这个执行环境决定了变量的生命周期,以及哪一部分代码可以访问其中的

从头开始学JavaScript 笔记(二)——变量及其作用域

一.变量 ECMAscript变量是松散型变量,所谓松散型变量,就是变量名称可以保存任何类型的数据,每个变量仅仅是一个用于保存值的占位符. 定义:var firstDemo; 二.变量的作用域 2.1基本概念 使用var 定义变量:定义该变量的作用域的局部变量,这种定义变量的方法也被成为显式声明. 这么说不理解的话可以看看下面这个简单粗暴的例子: test();function test(){var firstDemo="hello";//定义局部变量 alert(firstDemo)

JavaScript笔记(二)——常用数组、字符串方法的应用

1.将字符串中的字符翻转,比如'hello',翻转成'olleh'. var arr=[]; function reverseString(str) { arr=str.split(""); arr=arr.reverse(); str=arr.join(""); return str;} reverseString("hello"); 2.计算一个整数的阶乘 function factorialize(num) { if(num<=1){

javascript笔记——jQuery插件开发的几种方式

jQuery插件开发分为两种: 1 类级别  类级别你可以理解为拓展jquery类,最明显的例子是$.ajax(...),相当于静态方法. 开发扩展其方法时使用$.extend方法,即jQuery.extend(object); $.extend({ add:function(a,b){return a+b;} , minus:function(a,b){return a-b;} }); 页面中调用: var i = $.add(3,2); var j = $.minus(3,2); 2 对象级

php深入学习笔记二( 函数内置函数 )

1. call_?user_?func_?array 调用用户自定义函数,第一个参数是函数名, 第二个参数是函数的参数 必须是是一索引数组 function foobar($arg, $arg2) { echo __FUNCTION__, " got $arg and $arg2\n"; } class foo { function bar($arg, $arg2) { echo __METHOD__, " got $arg and $arg2\n"; } } //

Javascript 笔记与总结(2-8)对象2

注意:标签属性与 DOM 对象属性的对应关系,绝大部分 2 者是相同的,例如 imgobj.src 属性对应 <img src=""> 中的 src 属性 例外:<div class="">中操作 class 属性用 divobj.className css 属性与 DOM 对象属性的对应关系,2 者通过 obj.style.css 属性名相对应,例如: obj.style.width obj.style.background 如果 css

Javascript 笔记与总结(2-7)对象

html: <h1>找对象</h1> <div id="div1"> <p>p1</p> <p>p2</p> <p>p3</p> </div> <div class="div2"></div> <input type="text" name="username"> js: