聊聊:Javascript中函数的四种调用模式

在 js 中 无论是函数, 还是方法, 还是事件, 还是构造器, ... 其本质都是函数. 只是处在不同的位子而已。

四种模式有:函数模式,方法模式,构造器模式,上下文模式

1.函数模式

特征: 就是一个简单的函数调用. 函数名的前面没有任何引导内容,其中this表示全局对象,在浏览器中是window。

比如:  

function foo () {}

var func = function () {};

...

foo();

func();

(function (){})();

2.方法模式

特征: 方法一定是依附于一个对象, 将函数赋值给对象的一个属性, 那么就成为了方法,其中this指的是这个依附的对象.

比如:

function f() {

   this.method = function () {};}var o = {   method: function () {} }
3.构造器调用模式

    特征:
1. 使用 new 关键字, 来引导构造函数.2. 构造函数中发 this 与方法中一样, 表示对象, 但是构造函数中的对象是刚刚创建出来的对象3. 构造函数中不需要 return, 就会默认的 return this

补充:1. 如果手动的添加 return, 就相当于 return this2. 如果手动的添加 return 基本类型; 无效, 还是保留原来 返回 this3. 如果手动添加 return null; 或 return undefiend, 无效4. 如果手动添加 return 对象类型; 那么原来创建的 this 就会被丢掉, 返回的是 return 后面的对象

由于构造函数只是给 this 添加成员. 没有做其他事情. 而方法也可以完成这个操作, 就 this 而言,构造函数与方法没有本质区别.
1. 工厂方法

   // 工厂就是用来生产的, 因此如果函数创建对象并返回, 就称该函数为工厂函数   function createPerson( name, age, gender ) {      var o = {};      o.name = name;      o.age = age;      o.gender = gender;      return o;   }

   // document.createElement() 

2. 构造方法3. 寄生式创建对象

   // 外表看起来就是构造方法, 但是本质不是的构造方法创建对象的方式   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‘ );

4. 混合式创建
一个案例:<!DOCTYPE h<html>

<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
<script>

function Foo() {
getName = function(){ alert(1); };
return this;
}
function getName() {
alert(5);
}
Foo.getName = function() { alert(2); };
Foo.prototype.getName = function() { alert(3); };

getName = function() { alert(4); };

Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1 一开始赋值全局的 getName 为 1, 然后返回 this

getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3

new new Foo().getName(); // 3

</script>
</html>

4.上下文调用模式

      上下文就是环境,也就是自定义设置this的含义.

语法:     1. 函数名.apply( 对象, [ 参数 ] );     2. 函数名.call( 对象, 参数 );

描述:     1. 函数名就是表示的函数本身, 使用函数进行调用的时候默认 this 是全局变量     2. 函数名也可以是方法提供, 使用方法调用的时候, this 是指当前对象.     3. 使用 apply 进行调用后, 无论是函数, 还是方法都无效了. 我们的 this, 由 apply 的第一个参数决定

注意:      1. 如果函数或方法中没有 this 的操作, 那么无论什么调用其实都一样.     2. 如果是函数调用 foo(), 那么有点像 foo.apply( window ).      3. 如果是方法调用 o.method(), 那么有点像 o.method.apply( o ).

 参数问题

无论是 call 还是 apply 在没有后面的参数的情况下( 函数无参数, 方法无参数 ) 是完全一样的.

   function foo() {      console.log( this );   }   foo.apply( obj );   foo.call( obj );

第一个参数的使用也是有规则的    1. 如果传入的是一个对象, 那么就相当于设置该函数中的 this 为参数    2. 如果不传入参数, 或传入 null. undefiend 等, 那么相当于 this 默认为 window

    foo();    foo.apply();    foo.apply( null );    foo.call( undefined );

 3. 如果传入的是基本类型, 那么 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 )

处理数组转换, 实际上就是将元素一个一个的取出来构成一个新数组, 凡是涉及到该操作的方法理论上都可以

  1. push, unshift  2. slice  3. 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 ] );

 求数组中的最大值

传统

   var max = arr[ 0 ];   for ( var i = 1; i < arr.length; i++ ) {      if ( arr[ i ] > max ) {         ...      }   }

还是利用 apply 可以展开数组的特性

   var arr = [ 123456,12345,1234,345345,234,5 ];   Math.max.apply( null, arr );

借用构造函数继承

   function Person ( name, age, gender ) {      this.name = name;      this.age = age;      this.gender = gender;   }

   // 需要提供一个 Student 的构造函数创建学生对象   // 学生也应该有 name, age, gender, 同时还需要有 course 课程   function Student ( name, age, gender, course ) {

      Person.call( this, name, age, gender );

      this.course = course;   }
时间: 2024-10-04 04:08:53

聊聊:Javascript中函数的四种调用模式的相关文章

JavaScript中函数的四种调用模式

理解函数的四种调用方法,可以有效的帮助我们分析和理解JavaScript代码.但是经常有人分不清楚或者不理解这四种调用模式,在JavaScript中,函数是一等公民,函数在JavaScript中是一个数据类型,而非像C#或其他描述性语言那样仅仅作为一个模块来使用.函数有四种调用模式,分别是:1.函数调用形式 2.方法调用形式 3.构造器调用形式 4.上下文调用形式(apply,call)这里所有的调用模式中,最主要的区别在于关键字 this 的意义.下面分别介绍这几种调用形式. 一.函数调用形式

javascript中函数的四种调用模式详解

介绍函数四种调用模式前,我们先来了解一下函数和方法的概念,其实函数和方法本质是一样,就是称呼不一样而已.函数:如果一个函数与任何对象关系,就称该函数为函数.方法:如果一个函数作为一个对象属性存在,我们就称之为方法.接下来就可以开始今天的主体. 1.函数调用模式. 就是通过函数来调用,规范写法为:function fn(){} fn(); 函数中this的指向->window.案例如下: var age = 38; var obj = { age: 18, getAge: function() {

Javascript中函数的四种调用方式

一.Javascript中函数的几个基本知识点: 1.函数的名字只是一个指向函数的指针,所以即使在不同的执行环境,即不同对象调用这个函数,这个函数指向的仍然是同一个函数. 2.函数中有两个特殊的内部属性:arguments和this. arguments主要是用来保存函数参数,arguments中的callee属性主要是用来指向拥有当前arguments的函数(理解Javascript参数中的arguments对象). 3.在ECMAScript5中规范了另一个函数属性:caller(Opera

函数的四种调用模式

函数的四种调用模式 1.函数模式 特征 就是一个简单的函数调用,函数名前面没有任何的引导内容 this含义 this在函数模式中表示全局对象,在浏览器中是windjow对象 2.方法模式 特征 方法一定是依附与一个对象,将函数赋值给对象的一个属性,那么就成为了方法 this含义 this在方法模式调用中表示所依附的这个对象 3.构造器调用模式 与方法模式的this的区别 由于构造函数知识给this添加成员,没有做其他事情,而方法也可以完成这个操作,就this而言,构造函数与方法没有本质区别 特征

函数的四种调用模式.上下文调用.call.apply

闭包:函数就是一个闭包,一个封闭的作用域; 返回函数,要返回多个函数就用一个对象封装一下, 立即执行函数+return 回调函数 JS动态创建的DOM,不会被搜索引擎抓取,对SEO不友好. /*window的name属性*/ function fn(){ console.log(this.name); } fn.call({name:"zhangsan"});//"zhangsan" console.log(); fn();//'' 打印空字符串,此时调用fn其中的

js中this的四种调用模式

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <ti

JavaScript (JS) 函数补充 (含arguments、eval()、四种调用模式)

1. 程序异常 ① try-catch语法    测试异常 try-catch语法代码如下: try { 异常代码;     try中可以承重异常代码, console.log("try")  出现异常代码后,正确代码不会执行 } catch (e) { console.log("e:"+e);  try中出现异常在e中展现出来 console.log("catch");  只有try中出现异常才执行这段代码 } finally { consol

函数的四种调用模型

函数的四种调用模式在 js 中 无论是函数, 还是方法, 还是事件, 还是构造器, ... 其本质都是函数. 只是处在不同的位子而已. 四种: 函数模式方法模式构造器模式上下文模式1. 函数模式 特征: 就是一个简单的函数调用. 函数名的前面没有任何引导内容. function foo () {} var func = function () {}; ... foo(); func(); (function (){})();this 的含义: 在 函数中 this 表示全局对象, 在浏览器中是

安卓中Activity的四种启动模式

Activity的四种启动模式 (示例图) 1.standard  标准的启动模式,在回退栈中,每次访问启动的activity都是一个全新的Activity.   2.singleTop     栈顶单一,在回退栈中,如果打开的Activity就是栈顶的Activity, 将重用栈顶的这个Activity.   3.singleTask     栈内唯一,在回退栈中,如果打开一个栈中已存在的Activity,它会把这个Activity之上的所有Activity都杀死,从而保证栈内唯一.   4.