函数的定义
(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(/function\s*([^(]*)/)[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(/function\s*([^(]*)/)[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);
}
}