ECMAScript学习笔记(四)

Posted by Csming on 2018-09-12

Function类型

在ECMAScript中,每个函数都是一个函数对象,都是Function类型的实例,且都和其他引用类型一样具有属性和方法。

函数名实际上是一个指向函数对象的指针,不会和某个函数绑定。

1
2
3
4
5
6
7
8
9
10
11
function sum(num1, num2) {
return num1 + num2;
}

// 相当于:

var sum = function(num1, num2) {
return num1 + num2;
};

var sum = new Function("num1", "num2", "return num1 + num2");

以上代码意味着,一个函数可能会有多个名字:

1
2
3
4
5
6
function sum(num1, num2) {
return num1 + num2;
}

var anothorSum = sum;
// 将一个anothorSum变量的值设置为sum的值。使得他们指向了同一个函数。

没有重载

ECMAScript函数是没有重载的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function addSomeNumber(num) {
return num + 100;
}

function addSomeNumber(num) {
return num + 200;
}
// 相当于

var addSomeNumber = function(num) {
return num + 100;
}

var addSomeNumber = function(num) {
return num + 200;
}

以上代码将addSomeNumber变量赋值为先后两个函数对象。后一个函数对象覆盖了前一个函数对象嗯。

函数的声明&函数表达式

对于函数声明,解析器会先读取声明,并使其在执行任何代码之前可用。而对于函数表达式,则必须等到解析器执行到他所在的代码行才会被解释。

作为值的函数

ECMAScript中的函数名本身就是一个变量,所以所有的函数都可以被当做值来使用。所以可以把一个函数传递给另一个函数,并且可以将一个函数作为另一个函数的结果返回。

1
2
3
4
5
6
7
8
9
10
11
function callSomeFunction(someFunction, someArgument) {
return someFunction(someArgument);
}

function add10(num) {
return num + 10;
}

var result1 = callSomeFunction(add10, 10);

alert(result1); // 20

1
2
3
4
5
6
7
8
9
10
11
12
13
function createComparsionFunction(propertyName) {
return function(object1, object2) {
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
};
}

函数内部属性

arguments和this

arguments的作用是用于保存函数参数。而这个对象还有一个叫callee的属性,用于指向拥有这个arguments对象的函数。

对于一个递归函数:

1
2
3
4
5
6
7
function factorial(num) {
if (num <= 1) {
return 1;
}else {
return num * factorial(num - 1);
}
}

如果factorial函数被赋给另一个变量,而factorial变量被赋值为null的话……那么上述代码就挂了。

所以有了callee对象,就衍生了下面这样的用法:

1
2
3
4
5
6
7
function factorial(num) {
if (num <= 1) {
return 1;
}else {
return num * arguments.callee(num - 1);
}
}

这样函数名和函数体就解耦了。

另一个对象this 其行为跟Java中的this类似。this引用的是函数赖以执行的环境对象。

eg: 在网页的全局作用域中调用函数时,则this引用的是window。

1
2
3
4
5
6
7
8
window.color = "red";
var o = {color: "blue"};

function sayColor() {
alert(this.color);
}
o.sayColor = sayColor;
o.sayColor(); // blue

ECMAScript 5规范了另一个函数对象的属性:caller。这个属性保存了调用当前函数的函数的引用。若在全局作用域中调用当前函数,则该值为null

函数属性和方法

每个函数都包含:length和prototype两个属性。

length: 表示函数希望接收的明明参数的个数
prototype: 包含了引用类型的所有实例方法

每个函数包含了:apply()和call()两个方法。这两个方法的用途都是在特定的作用域中调用函数。

apply(): 接收两个参数:运行函数的作用域,参数数组。
call(): 接收两个参数:运行函数的作用域,传入其余参数。

这两个方法能够扩充函数赖以运行的作用域。

eg:

1
2
3
4
5
6
7
8
9
10
11
window.color = "red";
var o = {color: "blue"};

function sayColor() {
alert(this.color);
}
sayColor(); // red

sayColor.call(this); // red
sayColor.call(window); // red
sayColor.call(o); // blue

基本包装类型

ECMAScript提供了三个特殊的引用类型:Boolean、Number、String.

每当读取一个基本类型值的时候,后台就会创建一个对应基本包装类型的对象。

引用类型和基本包装类型的区别在于对象的生存期:使用new操作符创建的引用类型的实例,在执行流离开当前作用域前都会一直被存在内存中。而自动创建的基本包装类型的对象,只存在于一行代码的执行瞬间之后会立即被销毁。

那么,就不能在运行时为基本类型值添加属性和方法了。

各种基本类型的用法之类的跟Java里面差不多,我就不记录了。嗯。

单体内置对象

内置对象就是:ECMAScript实现提供的不依赖于宿主环境的对象。

Global对象

Global不属于其他任何对象的属性或者方法,最终都是他的属性和方法。

1.URI编码方法:

encodeURI()和encodeURIComponent()方法可以对URI进行编码。

2.eval()方法

eval()方法相当于一个完整的ECMAScript解析器。能够接受一个要执行的ECMAScript代码的字符串。

然后就执行了。

4.window对象

Math对象

跟Java里的差不多,就懒得记了。