函数的定义
(1) 函数的声明: function add(x, y) { return x + y; } (2)函数表达式 var add = function (i, j) { reutrn i + j; } (3)对象实例化(实际编程一般不会用),定义在全局。 var add = new Function ('i', 'j', "return (i + j)");
函数的属性:
prototype:add
constructor:function add(i, j)
__proto__ : Object, 来自于实例初始化的prototype
构造函数:
prototype是函数的专利,只有函数才有prototype属性。
构造函数与普通函数的区别
(1)本质上没有什么区别。
(2)构造函数通常会有this指定实例属性,原型对象上面通常有一些公用方法
(3)构造函数命名通常第一个字母大写。
函数的调用
(1)构造函数调用模式
var person1 = new Person('hg');
var person2 = new Person('wj');
(2)方法调用模式,就是调用对象的方法
person1.say();
(3)函数调用模式
例子(1) function aaa() { this.a = 1; alert(this + " aaa " + this.a); function bbb() { alert(this + " bbb " + this.a); } bbb(); } //这里都可以弹出1. 因为 this.a = 1, 这个this == window。所以a挂在window上面了。 aaa(); //注意:两个this指向的都是window。 例子(2) //获取对象构造函数名称 function type(obj) { return obj && obj.constructor && obj.constructor.toString().match(/functions*([^(]*)/)[1]; } function AAA() { this.aa = 1; alert(this + " aaa " + this.aa); this.bbb = function () { alert(type(this)); //AAA alert(this + " bbb " + this.aa); } } var A = new AAA(); //[object Object] aaa 1 A.bbb(); //[object Object] bbb 1 alert(window.A.aa); //1 alert(window.aa); //undefined 例子(3) //获取对象构造函数名称 function type(obj) { return obj && obj.constructor && obj.constructor.toString().match(/functions*([^(]*)/)[1]; } function AAA() { this.aa = 1; alert(this + " aaa " + this.aa); function bbb() { alert(type(this)); //Window alert(this + " bbb " + this.aa); } bbb(); //[object Window] bbb undefined } var A = new AAA(); //[object Object] aaa 1 // A.bbb(); 无法调用,因为是bbb局部函数, alert(window.A.aa); //1 alert(window.aa); //undefined
(4)apply,call调用模式
Function.prototype.apply;
apply是函数上面的方法。所有的函数都可以调用这个方法。
如果获取一个对象类型的函数:
Object.prototype.toString.apply(obj);
Object.prototype.toString.apply(1234); //number
apply是一个借用的功能。
A.apply(B, args); // B函数-->>借用-->>A函数. 操作参数args。
call(this, x, y); //call 后面的参数,分开传入,apply传入的是一个数组。
(5) bind方法!!!
var test = B.bind(A, argus);
test();
bind绑定了对象和参数。返回一个函数,需要的时候,执行就好了。
二,arguments
(1) Array-like
只是长得像数组,但不是数组,可以有arguments[index]
和arguments.length的方法,但其他数组方式无法使用。
function test(x, y, z) {
alert(type(arguments)); //object
var args = Array.prototype.slice.apply(arguments);
alert(type(args)); //Array
}
test(1,3,4,5,6);
弹出: 第一个是Object对象,第二个是Array数组。
用这个把参数给转换为数组,也可以。
var args = Array.prototype.slice.apply(arguments);
(2) arguments.callee
指向函数本身. arguments.callee();调用函数本身。
进行递归的方式。
var hga = 3; function test(a) { if (a != 0) { alert(a); a--; } else { return ; } arguments.callee(a); } test(hga);
三,递归
不用arguments.callee();就要防止,函数名被篡改。
四,闭包:在函数中定义函数,而被定义的函数,调用了父函数中的变量。
(function() { var a = 0; function b() { a = 1; debugger; } })(); 闭包的使用场景:改变作用域,将函数的变量,变为私有变量。
后期会专门写一篇关于闭包的问题。
五,First-class function.
JS的函数,可以作为变量保存,可以作为参数传递,可以作为返回值返回。
(1)函数颗粒化。 比如实现一个add(num1)(num2)(num3);的这种作用链调用的函数。 一个不定量,累加的。回调。 function add(value) { var helper = function (next) { value = typeof(value) === 'undefined' ? value : value + next; return helper; } helper.valueOf = function () { return value; } return helper; } console.log(add(1)(2)(3)); //实现方式是,首先在函数内定义一个函数,helper,判断传入的参数是否是undefined. //如果是,value值就不变,如果不是,就更新value值。 //函数返回的是一个helper的函数。 (2)回调,做异步回调 在ajax中,在success返回成功时,做function() //封装了一个ajax的异步调用。 function ajax.get(url, callback) { var createXHR = function () { var xhr; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { xhr = new ActiveXObject('Microsoft.XMLHTTP'); } return xhr; } var xhr = createXHR(); if (xhr) { xhr.open('get', url, true); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (xhr.status == 200) { callback.success(xhr); } else { callback.fail(xhr); } } } xhr.send(null); } }