JavaScript基础(五)函数

函数:是一块JavaScript代码,被定义一次,但可执行和调试用多次。JS中的函数也是对象,所以JS函数可以像其他对象那样操作和传递,所以我们也常常叫函数为函数对象。

function foo(x,y){

    if(typeof x === 'number' && typeof y ==='number'){

        return x + y;

     }else{

        return 0;

     }

 }

foo(1,2);//3

重点

不同的调用方式

直接调用

foo();

对象方法

o.method();

构造器

new foo();

call/apply/bind调用方式

fun.call(o);


创建函数 声明 vs 表达式

函数声明

function add(a,b){

    a = +a;

    b = +b;

    if(isNaN(a) || isNaN(b)){

        return;

     }

    return a + b;

 }

函数表达式

//function  variable

var add = function(a,b){

    //todo

 }

(function(){ //立即执行表达式

    //todo

 })();


return function(){

    //todo

 };


var add = function foo(a,b){ //命名是函数表达式

    //todo

 }   

函数声明和函数表达式的区别

函数声明前置

//函数声明

var num add(1,2);

console.log(num);//return 3

function add(a,b){

    a = +a;

    b = +b;

    if(isNaN(a) || isNaN(b)){

        return;

     }

    return a + b;

 }

//函数表达式

var num add(1,2);

console.log(num);//TypeError:undefined is not a function//不是一个方法

var add = function add(a,b){

    a = +a;

    b = +b;

    if(isNaN(a) || isNaN(b)){

        return;

     }

    return a + b;

 }

命名函数表达式(nfe)

var func = function nfe() {};

alert(func === nfe); //ie6-8 false  ie9+ error

//递归调用

var func = function nfe(){ 

    //todo

    nfe();

 }

Function构造器

//a ,b 形参 最后一个形参是函数的方法体

var func  = new Function('a','b','console.log(a + b);');

func(1,2);//3

var func  = Function('a','b','console.log(a + b);');

func(1,2);//3


Function('var localVal = "local";console.log(localVal);')();//colal  localVal仍为局部变量

console.log(typeof localVal);//undefined


var globalVal = 'global';

(functiong(){

    var localVal = 'local';

    Function('console.log(typeof localVal,typeof global);')(); //local不可访问,全局变量global可以访问

 })();//undefined,String;


This 

全局this(浏览器)

console.log(this.document === document);//true

console.log(this === window);//true


this.a = 37;

console.log(window.a);37

一般函数的this(浏览器)

function f1(){

    return this;

 }

f1() === window;//true,global object


function f2(){

    "use strict";//see strict mode 严格模式

    return this;

 }

f2() === undefined;//true


作为对象方法的函数的this

var o = {

    prop : 37,

    f:function(){

        return this.prop;   

     }

 };

console.log(o,f(););//37


var o ={prop:37};

function independent(){

    return this.prop;

 }

o.f = independent;

console.log(o.f());//logs 37

对象原型链上的this

var o = {f.function(){

    return this.a + this.b;

 }};

var p = Object.create(o);

p.a = 1;

p.b = 4;

console.log(p.f());

get/set 中的this用法和上面一样,构造器中的this和上面还是一样的


call / apply方法与this

function add(c,b){

    return this.a + this.b + c + d;

 }

var o = {a:1,b:3};

add.call(o,5,7);//1+3+5+7 =16  //o 给this

add.apply(o,[10,20]);//1+3+10+20 =34 // o 给this

function bar(){

    console.log(Object.prototype.toString.call(this)); //拿到this的标签

 }

bar.call(7);//Object Number

bind方法与this

function f(){

    return this.a;

 }

var g = f.bind({a:"test"});//把那个对象的属性设置成this

console.log(g());//test

var o = {a:37,f:f,g:g};

console.log(o.f(),o.g());//37,test


函数属相 和 arguments

function foo(x,y,z){

    arguments.length;//2 实参个数,因为foo调用时只传了2个形参,所以实参个数为2

    arguments[0];//1

    arguments[0] = 10;//绑定x

    x;//10

    arguments[2] = 100;//参数没有传z,所以arguments无法修改参数z的值,返回仍然是undefined

    z;//undefined;

    arguments.callee === foo;//true

 }

foo(1,2);

foo.length;//3  形参个数为3

foo.name;//"foo" 函数名是foo

注意:在"use strict"严格模式下 arguments无法改变参数的值,并且callee方法无法使用


apply 和 call 方法(浏览器)

function foo(x,y){

    console.log(x,y,this);

 }

foo.call(100,1,2);//1,2,number[100]

foo.apply(true,[3,4]);//3,4,boolean[true]

foo.apply(null);//undefined,undefined,window //'use strict' 严格模式下返回 undefined ,undefinde,null

foo.apply(undefined);//undefined,undefined,window //'use strict' 严格模式下返回 undefined ,undefinde,undefined


bind方法IE9以上提供的方法

this.x = 9; //全局变量9

var module = {

    x:81.

    getX:function(){ return this.x};

 }

module.getX();//81


var getX = module.getX;

getX() = 9;//指向全局变量this


var boundGetX = getX.bind(module); //重新指向module中的this

boundGetX();//81

bind与currying

function add(a,b,c){

    return a + b + c;

 }

var func = add.bind(undefined,100); //a绑定100 ,this = undefined

func(1,2);//103  100 + 1 + 2 =103 传了两个参数,所以a = 100

var func2 = add.bind(undefined,200);//a = 100 ,b =200 

func2(10);//310 100 + 200 + 10 = 310 //传了一个参数

使用场景

function getConfig(colors,size,otherOptions){

    console.log(colors,size,otherOptions);

 }

var defaultConfig = getConfig.bind(null,"#CC0000","1024*768");

defaultConfig("123");//"#CC0000","1024*768","123"

defaultConfig("456");"#CC0000","1024*768","456"

bind与new

function foo(){

    this.b = 100;

    return this.a;

 }

var func = foo.bind({a:1});

func();//1

new func();//b:100 new会湖忽略bind的作用

binde方法的模拟 科里化

function foo(){

    this.b = 100;

    retrun this.a;

 }

var func = foo.bind({a:1});

func();//1

new func();//{b:100}

//因为bind是IE9+才能使用的所以,在IE5上使用就需要模拟bind方法

if(!Function.prototype.bind){

    Function.prototype.bind = function(oThis){

        if(typeof this !== 'function'){

            throw new TypeError('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,aArgs.concat(Array.prototype.slice.call(arguments)));

         };

    fNOP.prototype = this.prototype;

    fBound.prototype = new fNOP();

    return fBound;

     };

 }


猜你喜欢

转载自blog.csdn.net/jianghai_csdn/article/details/79373065