• 函数的四种调用方式


    函数的四种调用模式

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

    四种:

    1. 函数模式
    2. 方法模式
    3. 构造器模式
    4. 上下文模式

    函数模式

    特征: 就是一个简单的函数调用. 函数名的前面没有任何引导内容.

    	function foo () {}
    	var func = function () {};
    	...
    	
    	foo();
    	func();
    	(function (){})();
    

    this 的含义: 在 函数中 this 表示全局对象, 在浏览器中是 window

    方法模式

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

    	function f() {
    		this.method = function () {};
    	}
    	var o = {
    		method: function () {} 
    	}
    

    this 的含义: 这个依附的对象.

    构造器调用模式

    创建对象的时候 构造函数做了什么?

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

    特征:

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

    补充:

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

    创建对象的模式

    1. 工厂方法
    	// 工厂就是用来生产的, 因此如果函数创建对象并返回, 就称该函数为工厂函数
    	function createPerson( name, age, gender ) {
    		var o = {};
    		o.name = name;
    		o.age = age;
    		o.gender = gender;
    		return o;
    	}
    	
    	// document.createElement() 
    
    1. 构造方法
    2. 寄生式创建对象
    	// 外表看起来就是构造方法, 但是本质不是的构造方法创建对象的方式
    	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' );
    
    1. 混合式创建

    上下文调用模型

    上下文 就是环境, 就是自定义设置 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 );
    
    1. 如果传入的是基本类型, 那么 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 ] );
    
  • 相关阅读:
    System.InvalidOperationException: 找到多个与名为“Home”的控制器匹配的类型。
    MemoryStream和FileStream
    js的eval函数解析后台返回的json数据时为什加上圆括号eval("("+data+")"),而HTML页面定义的数据不用
    字符串转数组和数组转字符串
    npoi导入--从varchar数据类型到datetime数据类型转换产生一个超出范围的值问题
    IIS配置 Web部署 svg/woff/woff2字体 404错误
    委托由浅入深学习
    JavaScriptSerializer返回一条Json,页面获取值问题,数据绑定
    一文总结 CPU 基本知识
    Spring原理只要看这篇文章就够了
  • 原文地址:https://www.cnblogs.com/jiaozhuo/p/5751002.html
Copyright © 2020-2023  润新知