/*
函数对象
JS中的函数就是对象,函数对象连接到Function.prototype,而Function.prototype对象本身连接到Object.prototype
每个函数在创建时会附加两个隐藏属性:
函数对象数的上下文
实现函数行为的代码
每个函数的prototype拥有一个constructor属性,这个属性的值为该函数的对象
*/
var someFunction = function() {};
console.log(someFunction.prototype.constructor === someFunction);
//输出:
//true
//----------------------------------------------------------------------------------------
/*
函数字面量
一个内部函数除了可以访问自己的参数和变量,同时它也能自由访问它嵌套在其中的付函数的参数与变量
通过函数字面量创建的函数对象包含一个练到外部上下文的连接,称为闭包
调用
每个函数接收两个附加的参数:
this:值取决于调用的模式,一共有四种模式
arguments:
如果实际参数过多,超出的参数值会被忽略,但是可以从arguments访问到
如果实际参数过少,缺失的值会被替换为undefined
*/
someFunction = function(param1,param2){
//为函数调用模式,所以this指向全局对象,浏览器中为window
console.log(this);
console.log(param1,param2);
console.log(arguments.length,arguments);
};
someFunction("a");
someFunction("a","b","c");
//输出:
// Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
// a undefined
// 1 ["a"]
// Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
// a b
// 3 ["a", "b", "c"]
//----------------------------------------------------------------------------------------
/*
四种调用模式:
*/
/*++++++++++++++方法调用模式++++++++++++++*/
/*
方法调用模式:
一个函数被保存为对象的一个属性时,称为一个方法
一个方法被调用时,this访问该方法所属的对象
如果调用表达式包含一个提取属性的动作,那么就是当做一个方法来调用
*/
var obj = {
name : "obj name",
method : function(){
console.log(this);
}
};
obj.method();
//输出:
// Object {name: "obj name", method: function}
/*++++++++++++++函数调用模式++++++++++++++*/
/*
函数调用模式:
一个函数并非一个对象的属性,那么它就是被当做一个函数来调用
this被绑定到全局对象
*/
//函数表达式形式
var functionInvocation_1 = function(){
console.log(this);
};
//函数声明形式
function functionInvocation_2(){
console.log(this);
}
//函数所在作用域不为全局作用域,this也指向全局对象
function functionInvocation_3_parent(){
//作用域为函数functionInvocation_3_parent内部作用域
function functionInvocation_3(){
//this指向全局对象
console.log(this);
}
functionInvocation_3();
}
functionInvocation_1();
functionInvocation_2();
functionInvocation_3_parent();
//输出:
// Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
// Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
// Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
/*++++++++++++++构造器调用模式++++++++++++++*/
/*
构造器调用模式:
一个函数前面带上new来调用,那么将会创建一个连接到该函数prototype成员的新对象,同时this指向这个新对象
不推荐使用new形式的构造器函数
如果使用了构造器调用方式,且返回值不是一个对象,则返回this所指的对象
*/
var SomeConstructor = function(){
console.log(this);
};
new SomeConstructor();
//输出:
// SomeConstructor {}
/*++++++++++++++apply调用模式++++++++++++++*/
/*
apply调用模式:
this指向第一个参数,如果为null,则指向全局对象
*/
var applyInvocation = function(){
console.log(this);
};
var applyInvocationObj = {
name : "applyInvocationObj name"
};
applyInvocation = applyInvocation.apply(applyInvocationObj);
//输出:
// Object {name: "applyInvocationObj name"}
//----------------------------------------------------------------------------------------
/*
参数
当函数被调用时,会得到免费配送的参数:arguments
arguments并不是一个数组,而是一个类似于数组的对象,它拥有length属性,但没有任何数组的方法
返回
一个函数总会返回一个值,如果没有指定,将返回undefined
*/
someFunction = function(){
console.log([].splice);
console.log(arguments.splice);
};
console.log(someFunction());
//输出:
// function splice() { [native code] }
// undefined
// undefined
/*
解释:
第一行输出数组的splice方法
第二行输出arguments,可以看到它没有数组的splice方法,它并不是一个数组
第三行输出someFunction的返回值,由于没有显式返回,为undefined
*/
//----------------------------------------------------------------------------------------
/*
扩充类型的功能
基本类型的原型是公用结构,所以在类库混用时需要小心,保险的做法就是只在确定没有该方法的时候才添加它
递归
JS不提供尾递归的优化(所谓尾递归优化,就是在一个函数返回自身递归嗲用的结果,那么调用过程会被替换为一个循环,可以显著提高速度)
作用域
作用域控制着变量与参数的可见性及生命周期
只有函数作用域,没有块级作用域
在函数体的顶部声明函数中可能用到的所有变量
闭包
内部函数可以访问定义他们的外部函数的参数和变量
通过闭包,内部函数可以拥有比它的外部函数更长的生命周期
应当避免在循环中创建函数
模块
模块是一个提供接口却隐藏状态与事项的函数或对象
模块模式利用了函数作用于和闭包来创建被绑定对象与私有成员的关联
使用模块模式可以摒弃全局变量的使用,促进了信息隐藏和其他优秀的设计实践
级联
让某些不返回任何值得方法返回this,就可以启用级联
*/
《JavaScript语言精粹》--第4章:函数
最新推荐文章于 2022-12-28 19:52:59 发布