对js中Function的浅见
2016-02-26 21:59
597 查看
它到底是什么
String Array 都是系统内置对象(已经定义好,可以直接使用)当然,这货也是一样,我们之前定义的函数,其实就是一个这货的实例。
在JS中,所有的对象都是由函数实现的,函数的数据类型是object。So,我们以前定义的函数也是一个对象。
几种写法
另外,如果函数没有明确的返回值,或者调用了没有参数的return,那么它真正返回的值是undefined
arguments
arguments只有在代码运行的时候才起作用,它是一个数组(准确的说是伪数组),保存函数的参数。
Length
我们需要了解两个东东,形参与实参(不同的资料书籍可能叫法有所差异)
形参:函数定义的时候的参数 实参:调用函数的时候传递的参数
length指的是形参个数 arguments.length指的是实参个数
call apply
1,借用另一个对象的方法 2,替换this指向
Apply方法 调用函数,并用指定对象替换函数的this值,同时用指定数组替换函数的参数。
Call方法 调用一个对象的方法,用另一个对象替换当前对象。
Function.apply(obj,args)方法能接收两个参数
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args-->arguments)
我们通过如下方式将其转换成数组
还可以实现继承,在上篇文章中说过,这里不做赘述。
caller callee
caller属性 获取调用当前函数的函数。caller属性只有当函数正在执行时才被定义。
返回函数调用者,主要用于察看函数本身被哪个函数调用.
callee属性 返回正被执行的 Function 对象,即指定的Function 对象的正文。
如下是一个递归算法 - 计算 1+2+3+4+...+n
什么是递归? 可以这样理解,一个方法,自己调用自己,用上一次调用得出的结果作为这次的参数。
传统方式的缺点:
1、破坏了,零重复法则,当一旦函数名称更改,需要更改多处
2、fn是一个全局变量,fn内部一般使用局部变量,而这里是一个全局变量,这是一个潜在的全局变量污染
优点:这样就让代码更加简练。又防止了全局变量的污染
constructor prototype
constructor属性,就是用来构造对象实例的函数引用。
prototype属性,获取对象的原型。
每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。
contructor,prototype属性是系统自动生成的。但本质上只是是函数对象的属性而已。
对象是一个函数,而函数对象含有contructor,prototype等属性,
那么实例化的过程就是拷贝构造函数属性的过程,所以每个实例自然就拥有了contructor,prototype这两个属性。
自定义对象:函数实现的--函数又是Function的一个实例,所以这个自定义对象含有Function对象的一切属性和方法
bind
Bind方法,创建具有与原始函数相同的主体的绑定函数。 在绑定功能中,this对象解析为传入的对象。 该绑定函数具有指定的初始参数。
为了能在改变了上下文之后继续引用到this,大家通常选择使用self that _this 等方式先保存起来。这是完全可以的,现在有了bind:
再看一眼:
想到了什么?call? apply? 没错,看下面三者的区别:
好消息是,IE8以下并不支持。肿么办?
没关系,大牛们写好了,我们来看一下
最后:
JS中,函数的使用是非常之灵活,比如闭包、立即函数、等等等等,以后有机会专门讨论。
String Array 都是系统内置对象(已经定义好,可以直接使用)当然,这货也是一样,我们之前定义的函数,其实就是一个这货的实例。
在JS中,所有的对象都是由函数实现的,函数的数据类型是object。So,我们以前定义的函数也是一个对象。
几种写法
function fn1(a,b){ return a+b; } //前面表示参数,后面表示函数语句 var fn2 = new Function("a","b","return a+b"); // 匿名函数 var fn3=function(a,b){ return a+b; } console.log(fn1(1,2)); console.log(fn2(1,2)); console.log(fn3(1,2)); // 注意,一定要在声明函数的后面调用
另外,如果函数没有明确的返回值,或者调用了没有参数的return,那么它真正返回的值是undefined
function fn(){ //..... } function fn1(){ return; } console.log(fn()===undefined); // true console.log(fn1()===undefined); // true
arguments
arguments只有在代码运行的时候才起作用,它是一个数组(准确的说是伪数组),保存函数的参数。
function fn(){ var sum=0; for(var i=0;i<arguments.length;i++){ sum+=arguments[i]; } return sum; } var sum = fn(1,2); var sum2 = fn(1,2,3); console.log(sum); // 3 console.log(sum2); // 6 function fn1(a,b,c,d){ console.log(arguments.length); console.log(arguments[0]); } fn1(); // 0 、 undefined fn1(1); // 1 、 1 fn1('a',2); // 2 、 a fn1('李志',2,3); // 3 、 李志 fn1('李B',2,2,3,4,4); // 6 、 李B
Length
我们需要了解两个东东,形参与实参(不同的资料书籍可能叫法有所差异)
形参:函数定义的时候的参数 实参:调用函数的时候传递的参数
length指的是形参个数 arguments.length指的是实参个数
function fn(a, b) { console.log(fn.length); console.log(arguments.length); } fn(1, 2); // 2 2 fn(1); // 2 1
call apply
1,借用另一个对象的方法 2,替换this指向
Apply方法 调用函数,并用指定对象替换函数的this值,同时用指定数组替换函数的参数。
Call方法 调用一个对象的方法,用另一个对象替换当前对象。
//对象1 var obj1={ getAllStudentsNumbers:function(sum,sum1){ return sum+sum1} }; //对象2 var obj2={ getDetail:function(){ return {name:'阿拉三',age:'18'} } }; console.log(obj1.getAllStudentsNumbers.call(obj2,10,200)); // 210 console.log(obj1.getAllStudentsNumbers.apply(obj2,[10,200])); // 210
Function.apply(obj,args)方法能接收两个参数
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args-->arguments)
我们通过如下方式将其转换成数组
/* slice : 截取数组,返回的还是数组,这里我们截取全部 */ var divs = document.getElementsByTagName("div") var domNodes = Array.prototype.slice.call(divs);
还可以实现继承,在上篇文章中说过,这里不做赘述。
caller callee
caller属性 获取调用当前函数的函数。caller属性只有当函数正在执行时才被定义。
返回函数调用者,主要用于察看函数本身被哪个函数调用.
function fn() { //判断某函数是否被调用 if (fn.caller) { alert(fn.caller.toString()); } else { alert("函数直接执行"); } } function fn1() { fn(); } fn1(); fn();
callee属性 返回正被执行的 Function 对象,即指定的Function 对象的正文。
如下是一个递归算法 - 计算 1+2+3+4+...+n
什么是递归? 可以这样理解,一个方法,自己调用自己,用上一次调用得出的结果作为这次的参数。
传统方式的缺点:
1、破坏了,零重复法则,当一旦函数名称更改,需要更改多处
2、fn是一个全局变量,fn内部一般使用局部变量,而这里是一个全局变量,这是一个潜在的全局变量污染
var fn=function(n){ return n>0 ? n+fn(n-1) : 0; } console.log('采用传统方式:'+fn(10));
优点:这样就让代码更加简练。又防止了全局变量的污染
var fn=(function(n){ return n>0 ? n+arguments.callee(n-1) : 0; })(10); console.log('采用callee方式: '+fn);
constructor prototype
constructor属性,就是用来构造对象实例的函数引用。
prototype属性,获取对象的原型。
每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。
contructor,prototype属性是系统自动生成的。但本质上只是是函数对象的属性而已。
对象是一个函数,而函数对象含有contructor,prototype等属性,
那么实例化的过程就是拷贝构造函数属性的过程,所以每个实例自然就拥有了contructor,prototype这两个属性。
自定义对象:函数实现的--函数又是Function的一个实例,所以这个自定义对象含有Function对象的一切属性和方法
var product = function(){} /*自动有一个 prototype属性 它是一个对象--- 原型对象*/ /* product.prototype也是对象,对象都是函数实现的,这货也包含Function对象的一切属性和方法,所以他也有。*/ product.prototype.buy=function(){} product.prototype={}
bind
Bind方法,创建具有与原始函数相同的主体的绑定函数。 在绑定功能中,this对象解析为传入的对象。 该绑定函数具有指定的初始参数。
为了能在改变了上下文之后继续引用到this,大家通常选择使用self that _this 等方式先保存起来。这是完全可以的,现在有了bind:
var obj={ fn1:function(){ console.log(1); }, fn2:function(){ console.log(2); }, fn3:function(fn){ fn(); console.log(3); }, fn4:function(){ // var that=this; // 还保存吗? // this.fn3(function(){ // console.log(4); // that.fn1(); // that.fn2(); // }); this.fn3(function(){ console.log(4); this.fn1(); this.fn2(); }.bind(this)); // 咦,发生什么? }, } obj.fn4();
再看一眼:
var foo={ x:3, } var bar=function(){ console.log(this.x); } bar(); var boundFunc=bar.bind(foo); boundFunc();
想到了什么?call? apply? 没错,看下面三者的区别:
fn1.hello.call(fn2,1,2,3); fn1.hello.apply(fn2,[1,2,3]); fn1.hello.bind(fn2)(1,2,3);
好消息是,IE8以下并不支持。肿么办?
没关系,大牛们写好了,我们来看一下
if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () {}, fBound = function () { return fToBind.apply(this instanceof fNOP ? this : oThis || this , aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; }; }
最后:
JS中,函数的使用是非常之灵活,比如闭包、立即函数、等等等等,以后有机会专门讨论。
相关文章推荐
- JS继承方式详解
- 160227、javascript特效
- 160226、js常用的验证
- Gson和Fastjson解析对比
- js原型及原型链
- JavaScript动态加载ul标签
- web小游戏 2048制作(四):过场动画 showanimation2048.js
- web小游戏 2048制作(三):辅助函数 support2048.js
- web小游戏 2048制作(二):游戏主逻辑 main2048.js
- 利用Gson实现简单的json字符串解析
- 使用javascript正则表达式实现遍历html字符串
- JSP页面跳转的几种实现方法
- js 获得当前日期
- 在javascript中取页面中的值
- js 推断 当页面无法回退时(history.go(-1)),关闭网页
- [javascript-code-snippet]javascript代码段
- javascript svg 页面 loading
- JavaScript跨域总结与解决办法(转)
- web端输出打印地图(ArcGIS api for Javascript)一、地图打印模板的制作
- js学习笔记1(变量、作用域、内存)