【转】函数的四种调用方式
函数的四种调用模式
在 js 中 无论是函数, 还是方法, 还是事件, 还是构造器, ... 其本质都是函数. 只是处在不同的位子而已.
四种:
- 函数模式
- 方法模式
- 构造器模式
- 上下文模式
函数模式
特征: 就是一个简单的函数调用. 函数名的前面没有任何引导内容.
function foo () {}
var func = function () {};
...
foo();
func();
(function (){})();
this 的含义: 在 函数中 this 表示全局对象, 在浏览器中是 window
方法模式
特征: 方法一定是依附于一个对象, 将函数赋值给对象的一个属性, 那么就成为了方法.
function f() {
this.method = function () {};
}
var o = {
method: function () {}
}
this 的含义: 这个依附的对象.
构造器调用模式
创建对象的时候 构造函数做了什么?
由于构造函数只是给 this 添加成员. 没有做其他事情. 而方法也可以完成这个操作, 就 this 而言,
构造函数与方法没有本质区别.
特征:
- 使用 new 关键字, 来引导构造函数.
- 构造函数中发 this 与方法中一样, 表示对象, 但是构造函数中的对象是刚刚创建出来的对象
- 构造函数中不需要 return, 就会默认的 return this
补充:
- 如果手动的添加 return, 就相当于 return this
- 如果手动的添加 return 基本类型; 无效, 还是保留原来 返回 this
- 如果手动添加 return null; 或 return undefiend, 无效
- 如果手动添加 return 对象类型; 那么原来创建的 this 就会被丢掉, 返回的是 return 后面的对象
创建对象的模式
-
工厂方法
// 工厂就是用来生产的, 因此如果函数创建对象并返回, 就称该函数为工厂函数 function createPerson( name, age, gender ) { var o = {}; o.name = name; o.age = age; o.gender = gender; return o; } // document.createElement()
- 构造方法
-
寄生式创建对象
// 外表看起来就是构造方法, 但是本质不是的构造方法创建对象的方式 function createPerson( name, age, gender ) { var o = {}; o.name = name; o.age = age; o.gender = gender; return o; } var p = new createPerson( 'jim', 19, 'male' );
-
混合式创建
上下文调用模型
上下文 就是环境, 就是自定义设置 this 的含义
语法:
- 函数名.apply( 对象, [ 参数 ] );
- 函数名.call( 对象, 参数 );
描述:
- 函数名就是表示的函数本身, 使用函数进行调用的时候默认 this 是全局变量
- 函数名也可以是方法提供, 使用方法调用的时候, this 是指当前对象.
- 使用 apply 进行调用后, 无论是函数, 还是方法都无效了. 我们的 this, 由 apply 的第一个参数决定
注意:
- 如果函数或方法中没有 this 的操作, 那么无论什么调用其实都一样.
- 如果是函数调用 foo(), 那么有点像 foo.apply( window ).
- 如果是方法调用 o.method(), 那么有点像 o.method.apply( o ).
参数问题
无论是 call 还是 apply 在没有后面的参数的情况下( 函数无参数, 方法无参数 ) 是完全一样的.
function foo() {
console.log( this );
}
foo.apply( obj );
foo.call( obj );
第一个参数的使用也是有规则的
- 如果传入的是一个对象, 那么就相当于设置该函数中的 this 为参数
-
如果不传入参数, 或传入 null. undefiend 等, 那么相当于 this 默认为 window
foo(); foo.apply(); foo.apply( null ); foo.call( undefined );
- 如果传入的是基本类型, 那么 this 就是基本类型对应的包装类型的引用
- number -> Number
- boolean -> Boolean
- string -> String
除了 this 的参数外的参数
在使用 上下文调用的 时候, 原函数(方法)可能会带有参数, 那么这个参数在上下文调用中使用 第二个( 第 n 个 )参数来表示
function foo( num ) {
console.log( num );
}
foo.apply( null, [ 123 ] );
// 等价于
foo( 123 );
应用
上下文调用只是能修改 this, 但是使用的最多的地方上是借用函数调用.
将伪数组转换为数组
传统的做法
var a = {};
a[ 0 ] = 'a';
a[ 1 ] = 'b';
a.length = 2;
// 数组自带的方法 concat
// 语法: arr.concat( 1, 2, 3, [ 4, [ 5 ] ] );
// 特点不修改原数组
var arr = [];
var newArr = arr.concat( a );
由于 a 是伪数组, 只是长得像数组. 所以这里不行, 但是 apply 方法有一个特性, 可以将数组或伪数组作为参数
foo.apply( obj, 伪数组 ); // IE8 不支持
将 a 作为 apply 的第二个参数
var newArr = Array.prototype.concat.apply( [], a )
处理数组转换, 实际上就是将元素一个一个的取出来构成一个新数组, 凡是涉及到该操作的方法理论上都可以
- push, unshift
- slice
- splice
push 方法
用法: arr.push( 1 ); 将这个元素加到数组中, 并返回所加元素的个数
arr.push( 1, 2, 3 ); 将这三个元素依次加到数组中, 返回所加个数
var a = { length: 0 }; // 伪数组
a[ a.length++ ] = 'abc'; // a[ 0 ] = 'abc'; a.length++;
a[ a.length++ ] = 'def';
// 使用一个空数组, 将元素一个个放到数组中即可
var arr = [];
arr.push( a ); // 此时不会将元素展开, 而是将这个伪数组作为一个元素加到数组中
// 再次利用 apply 可以展开伪数组的特征
arr.push.apply( arr, a );
// 利用 apply 可以展开伪数组的特性, 这里就相当于 arr.push( a[0], a[1] )
slice
语法: arr.slice( index, endIndex )
如果第二个参数不传, 那么就是 从 index 一致获取到结尾
该方法不会修改原数组
var a = { length: 0 };
a[ a.length++ ] = 'abc';
a[ a.length++ ] = 'def';
// 假设他是一个数组, 就是应该 从 0 项开始截取到 最后
// 如果可以的话, 应该 a.slice( 0 )
// 但是他没有该方法
// 借用 数组的 slice, 将 this 转换成 这个伪数组
var arr = [];
var newArr = arr.slice.apply( a, [ 0 ] );
C# System.Data.OracleClient requires Oracle client software version 8.1.7 or greater
C# oracle 日期型字段,使用参数传值时,遇到ORA-01810: format code appears twice错误
C# oracle to_date 日期型 参数传值
windows2003两台服务器,局域网之间不能互相访问
windows2003服务器,时间每隔1小时自动同步一次
sqlserver 服务器主体 无法在当前安全上下文下访问数据库
电商设计V1(一):软件工程设计
Maven使用教程三:maven的生命周期及插件机制详解
JVM 学习笔记二 :JVM内存区域
- 最新文章
-
haproxy
elasticsearch 性能监控基础
curl以cookie的方式登录
定期删除elasticsearch 的index 索引
haproxy 日志配置
OOM killer(Out Of Memory killer)
定时删除elasticsearch的index
Linux 磁盘使用查看 查看使用磁盘程序 Monitoring disk activity in linux
Installing Language Tool in TexStudio
Xrdp vnc password failed
- 热门文章
-
TensorFlow Saver 保存最佳模型 tf.train.Saver Save Best Model
Difference between nn.softmax & softmax_cross_entropy_with_logits & softmax_cross_entropy_with_logits_v2
TensorFlow数据读取方式:Dataset API
How to use Data Iterator in TensorFlow
树莓派 温度监控 PWM 控制风扇 shell python c 语言
树莓派 引脚及接口图 AV接口顺序
树莓派 MPG视频硬件解码破解 Raspberry Pi Patch for MPEG-2, VC-1 license
日期控件 DatePicker 在ie8不能用
远程桌面连接时,复制本地文件到远程服务器,本地磁盘,没有盘符,显示未指定
win7系统 无线上网卡 共享网络,设置成wifi热点