@Dale-Lin
2017-12-26T15:24:47.000000Z
字数 3875
阅读 911
JavaScript
函数是一系列语句组成的一个整体,用于执行某一特定任务。
构造函数函数名首字母应该大写,并且使用 new
操作符调用。
function sayHellow() {
document.write('Hellow hope!');
}
//前面可以声明函数
sayHello();
//后面也可以声明函数
function size(width,height){
return width*height;
}
//定义函数size时使用了形参height和width,return返回后面表达式计算的值
var size1 = size(8,10);
//调用函数size时使用了实参8和10,此时size1是80
var WIDTH = 8;
var HEIGHT = 10;
var size2 = size(WIDTH,HEIGHT);
//WIDTH和HEIGHT是储存了实参的变量
function culSize(width,height,depth){
var area = width*height;
var volume = area*depth;
var sizes = [size,volume];
return sizes;
}
//在这个函数中sizes储存了一个数组
var area1 = culSize(6,6,6)[0];
var volume2 = culSize(6,6,6)[1];
//调用时加入了实参,并且调用返回数组中的不同值
var area = function (width,height) {
return width*height;
};
var size3 = area(2,3);
这类函数没有函数名,在解释器经过时执行一次
var area = ( function () {
var width = 2;
var height = 3;
return width*height;
}()
);
//最外层的括号表明这个函数是一个表达式,函数语句块结束后的括号令解释器经过时直接执行此函数
函数内的arguments
对象存在一个叫callee
的属性,该属性是一个指针,指向拥有该arguments
对象的函数。如下一个典型的阶乘函数:
function factorial(num){
if (num<=1){
return 1;}
else (return num*arguments.callee(num-1);)
}
//使用arguments.callee(num-1)替代factorial(num-1),降低函数名与程序的耦合度
函数内另一个特殊对象是this
,引用函数执行的环境对象,在全局作用域下,即为window
对象。(严格模式下undefined)
window.color = "red";
var o = {color: "blue",};
function sayColor(){
alert(this.color);
}
sayColor(); //red
o.sayColor = sayColor;
o.sayColor(); //blue
在ECMAScript中,函数也是一种对象,因此函数拥有属性和方法。
每个函数都有两个属性:length
和 prototype
length
length
表示函数预设的命名参数个数:
function sayName(name){
alert(name);
}
function sum(num1,num2){
return num1+num2;
}
function sayHi(){
alert('Hi');
}
console.log(sayName.length); //1
console.log(sum.length); //2
console.log(sayHi,length); //0
prototype
toString()
、valueOf()
等方法实际上都保存在 prototype
名下,只是通过各自对象的实例来进行访问。 prototype
属性无法枚举,不能使用 for-in
发现。每个函数都包含两个原生方法:apply()
和 call()
。这两个方法都用于在特定的作用域中调用某函数:
apply()
Function.prototype.apply()
/* 改变函数作用域 */
window.color = "red";
var o = {color: "blue"};
function logColor(){
console.log(this.color)
}
logColor(); //red
logColor.apply(o, ); //blue
/* 传递参数 */
function sum(num1,num2){
return num1+num2;
}
function callSum1(num1, num2){
return sum.apply(this, arguments); //使用arguments传入callSum1的全局环境和参数
}
function callSum2(num1, num2){
return sum.apply(this, [num1,num2]); //使用Array实例传入callSum1的全局环境和参数
}
console.log(callSum1(5,10)); //15
console.log(callSum2(10,10)); //20
call()
Function.prototype.call()
apply()
作用相同,但接受参数的方式不同。
function sum(num1,num2){
return num1+num2;
}
function callSum(num1, num2){
return sum.call(this, num1, num2);
}
console.log(callSum(10,10)); //20
与apply()
一样,在扩充作用域上的优势在于——对象和方法之间没有任何耦合关系。
bind()
bind()
,该方法会创造一个function实例,其this值与传给bind()
作为参数的对象/函数的this值绑定。
window.color = "red";
var o = {color: "blue"};
function sayColor(){
console.log(this.color);
}
var objectSayColor = sayColor.bind(o);
console.log(objectSayColor); //blue
toString()
or toLocaleString()
语法
eval(string)
接收以字符串形式表示的一串JS代码,并立刻执行(evaluates)。
解析器发现调用eval()
方法时,将传入的参数执行结果插入到原代码位置,因此这段代码与eval()
具有相同的作用域。
eval("function sayHi(){ alert('hi');}");
sayHi(); //"hi"
即使是在eval()
方法内声明的代码,在eval()
代码相同的作用域下也可以被访问。
如果eval()
接收的参数不是字符串,eval()
会将参数直接插入原位置,而不会执行。
eval(new String("2+2")); //return "2+2"
eval("2+2"); //return 4
var expression = new String("2+2");
eval(expression.toString()); //return 4
如果 间接 地使用eval()
,它将在全局作用域下起作用(忽略当前作用域):
function test(){
var x = 2, y = 4;
console.log(eval("x+y")); //直接调用,使用function本地作用域,6
var geval = eval;
console.log(geval("x+y")); //间接调用,使用全局作用域,throws ReferenceError,x、y未定义
}
在eval()
中创建的任何变量或函数都不会被提升,因为在解析代码时,它们包含在一个字符串中,只有在eval()
执行的时候创建。
eval()
执行时调用js解析器,因此运行效率比其他替代方案慢。
return 可以使函数提前返回,当 return 执行时,函数立即返回而不再执行余下语句。
一个函数如果没有返回值,则返回 undefined 。