JavaScript中函数

来源:互联网 发布:豆瓣读书软件 编辑:程序博客网 时间:2024/05/21 14:09

javaScript中函数有一种超级延时绑定的特点
函数中原型:

'use strict';var foo = function(a,b){    var c=a,d=b;    return c + d;}var fo = new foo(1,2);//不规范写法,仅作示例if(foo.__proto__ === Function.prototype){    console.log('foo的原型为Function.prototype')}if(Function.prototype.__proto__ === Object.prototype){    console.log('Function.prototype的原型为Object.prototype')}if(fo.__proto__ === foo.prototype){    console.log('fo的原型为foo.prototype')}执行结果:foo的原型为Function.prototypeFunction的原型为Object.prototypefo的原型为foo.prototype

函数的调用模式:(注意this所绑定的值)
方法调用模式:this绑定为调用对象
函数调用模式:this绑定为全局对象
构造器调用模式:this绑定构造的对象
Apply调用模式:传递给函数this值

var sum = function(){    var a = this.a||0;    var b = this.b||0;    this.b=5;    return a+b;}var arg = {    a:1,    b:2}console.log(sum.apply(arg));//3console.log(arg.b);//5

参数:在函数调用时,函数会得到一个多余的形参arguments来放置多余的实参

var sum = function(){    var sum = 0,i = 0;    //arguments 不是数组 不能用for in语句    for(i;i<arguments.length;++i){        sum += arguments[i];    }    return sum;}console.log(sum(1,2,3,4,5));

返回:new function() 在函数返回值不是的对象的情况下返回一个新对象(以function.prototype为原型)

异常:异常可以返回错误信息,免去层层解开栈的麻烦

function add(a,b){    if(typeof a !== 'number' || typeof b !=='number'){        throw{            name : 'Type error',            message : 'arguments is not number'        }    }    return a+b;}function test(){    try{        console.log(add(3,'e'));    }catch(e){        console.log(e.name + ':' + e.message);    }}test();执行结果:Type error:arguments is not number

作用域 var,let,const:

详见(http://es6.ruanyifeng.com/#docs/let)

let :在定义之前不可见,定义的作用域之外不可见
const:在定义之前不可见,定义的作用域之外不可见
var : 在定义之前其值为undefined,定义后在块级作用域之后可见

'use strict';console.log('**********定义块作用域前***********')console.log(a);//console.log(b);  b is not defined//console.log(c);  c is not defined{    console.log('**********定义模块作用域中定义之前***********')    console.log(a);    //console.log(b);b is not defined    //console.log(c);c is not defined    var a = 'var';    let b = 'let';    const c = 'const';    console.log('**********定义模块作用域中定义之后***********')    console.log(a);    console.log(b);    console.log(c);}console.log('**********定义作用域后***********')console.log(a);//console.log(b);  b is not defined//console.log(c);  c is not defined//letconst 不进行变量提升,即在定义完成前使用将报错 let x= x;也报错执行结果:**********定义块作用域前***********undefined**********定义模块作用域中定义之前***********undefined**********定义模块作用域中定义之后***********varletconst**********定义作用域后***********var

let 适用于 for(let i;…;…){}中
暂时性死区:外面定义的变量不对let 和 const 造成影响

var d = 'd',e = 'e';{    console.log(d);   // console.log(e);e is not defined    var d = 'var';    let e = 'let';    console.log(d);    console.log(e);}执行结果:dvarlet

其他特性:
let变量不能在同一作用域下重复声明;
块级作用域:在快中声明的let/const变量和函数在块外不可引用

function f(){    console.log('outside');}(function(){    if(true){        //只允许在大括号里下申明        function f(){            console.log('inside');        }    }    f();//outside  在node中成功了}())
function f(){    console.log('outside');}(function(){    if(true){        var f =function(){            console.log('inside');        }    }    f();//inside}())

闭包
原理:内部函数可以访问他们的外部函数的参数和变量(除了this和arguments),而且内部函数比外部函数生命周期长。
作用:隐藏变量。
注意:内部函数在创建时并不绑定外部函数的变量,在执行时才绑定。但此时外部函数的变量可能已经不是原来的值了。

错误的使用let foo1 = function(){    let i = 0;    var fa = [];    for(i;i<4;i++){        fa[i] = function(){            console.log(i);        }    }    return fa;}var fa = foo1();for(let i=0;i<fa.length;i++){    fa[i]();}执行结果:4444
'use strict';let foo1 = function(){    let i = 0;    var fa = [];    var f = function(i){        return function(){            console.log(i);        }    }    for(i;i<4;i++){        fa[i] = f(i);    }    return fa;}var fa = foo1();for(let i=0;i<fa.length;i++){    fa[i]();}执行结果:0123来自道爷的忠告:不要在循环中创建函数

模块
模块的一般形式:一个定义了私有变量的函数的函数;利用闭包创建可以访问私有变量和函数的特权函数/对象,然后返回特权函数,或对象。
作用:隐藏状态,提供接口,介绍全局变量的使用。
一些变量放在全局变量中造成污染,放在函数中每次调用函数都有加载,而且不能保存修改后的值, 所以使用模块。

let module1 = function(){    let i = 1;    return function(){        var str = 'Q'+i;        i += 1;        return str;    }}var id = module1();console.log(id());console.log(id());console.log(id());执行结果:Q1Q2Q3

级联:
如何一个方法返回this(对象)则可以启用级联。

let ob2 = {    add1 : function(){        console.log('add1')        return this;    },    add2 : function(){        console.log('add2')        return this;    },    add3 : function(){        console.log('add3')        return this;    }}ob2.add1()   .add2()   .add3().add1();   执行结果:    add1    add2    add3    add1

柯里化
通过将函数和部分参数绑定的方法产生新的函数。

'use strict'let add = function(a,b){    return a + b;}//这段代码相当好。。。见语言精粹Function.prototype.method = function(name,func){    this.prototype[name] = func;    return this;}Function.method('curry',function(){    //将arguments转化为数组    var slice = Array.prototype.slice,    args = slice.apply(arguments);    var that = this;    return function(){        //内部函数不能访问外部函数的this和argumens        return that.apply(null,args.concat(slice.apply(arguments)));    }})let add1 = add.curry(1);console.log(add1(2));