让前端飞个人收藏

深入理解JavaScript函数

2019-05-10  本文已影响19人  88b61f4ab233

JavaScript中的函数

1. 函数的定义

函数声明语句定义一个函数

//计算阶乘的递归函数

function factorial(x){
    if (x<=1) return 1;
    return x*factotial(x-1);
}

函数定义表达式定义一个函数

var s= function sum(x,y){
    return x+y;
}

tips:以表达式方式定义的函数(特别适合用来定义那些只会用到一次的函数),函数名是可选的,
也就可以直接写成这样

var s= function(x,y){
    return x+y;
}

2.函数命名

3.函数的调用

example:

printprops({x:1})
var total = distance(0,1,2)+ distance(3,4,5)
var probability = factorial(5)/factoral(10)

概念:如果函数表达式是一个属性访问表达式(即该函数是一个对象的属性或者数组的一个函数),
那么该调用表达式就是一个方法调用表用表达式。
example:

//定义一个对象
    var person = {  
    name: lihua ,  
    age:  18 ,  
    sex:  女 ,  
    send: function(){//返回 person的name、age、sex
            this.message = this.name + this.age + this.age;
        } 
    };
    person.send();//这条语句就是函数的方法调用
    person.message; //得到name、age、sex相关信息

tips:
1.函数返回的值倘若是因为解释器到达结尾,返回值就是undefined;倘若函数返回是因为解释器执行到一条return语句,
则返回return语句后面的值;如果return语句后面没有值则返回undefined。
2.在ECMAScript3和在非严格模式下的ECMAScript5的函数调用规定中,this的值(调用上下文)的值是全局对象,但是在
严格模式下this的值却是undefined,因此可也用this来判断当前环境是否为严格模式,此外ECMAScript2015 (简称es6)严格模式请参考以下地址。
ECMAScipt的第六个版本 https://developer.mozilla.org/zh-CN/
3.方法调用和普通的函数调用的一个重要区别就是:调用上下文(即this的值),通常this关键字指向成为调用上下文的对象,
属性访问表达式:对象名.方法名(通常使用.运算符访问属性)或者"[]"进行属性访问操作。(this关键字的相关内容是十分重要的)

构造函数就是用来初始化先创建的对象,通常使用关键字new来调用构造函数,当使用new关键字来调用构造函数的时候就会自动
创建一个新的的空对象,而构造函数只需要初始化这个新对象的状态(属性和方法),调用构造函数的话,新的对象的原型(prototype)等于
构造函数的原型(prototype)属性,由此引出一个特性:通过同一个构造函数创建的所有对象都继承同一个相同的对象。

凡是没有形参的构造函数都可以省略圆括号,以下两行代码是等价的。

var fn = new Object();
var fn = new Object;

tips:
1.构造函数通常不使用return关键字,进行初始化新对象,执行完函数体,就调用构造函数表达式的计算结果作为新对象的值,显示返回。
2.倘若构造函数使用return语句返回一个对象,那么调用表达式的值就是这个对象,而不是this指向的对象。
3.构造函数里没有显式调用return时,默认是返回this对象,也就是新创建的实例对象。
4.return的是五种简单数据类型:String,Number,Boolean,Null,Undefined。这种情况下,忽视return值,依然返回this对象

1.call()方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表) this的值并不一定就是该函数执行真正的this值,在非严格模式下,倘若this的值指向nullundefined的话
会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。
2.apply()方法调用一个具有给定this值的函数,以及作为一个数组(或类似数组对象)提供的参数。
为this指定一个对象,使用apply时只需要写一次这个方法然后再另一个对象中继承它,继而不用在这个新的对象重新来写它。

tips:call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。

4.函数中的形参与实参

5.函数的闭包(!important)

tips
javascript是没有像Java、C++那样用一对“{}”括起来的块级作用域,但是在es6中可以使用let关键字实现块级作用域。

var scope = "global scope";  
function checkScope(){
    var scope = "local scope";
    function f(){return scope;}  
    return f();
}
checkScope();  //输出可以得到 local scope

  var name = "The Window";

  var object = {
    name : "My Object",

    getNameFunc : function(){
      return function(){
        return this.name;
      };

    }

  };

  alert(object.getNameFunc()());

example Two:

  var name = "The Window";

  var object = {
    name : "My Object",

    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };

    }

  };

  alert(object.getNameFunc()());

6.函数的属性、方法以及构造函数

function doSomething(){}
console.log(doSomething.prototype);
-----------------------------------  
结果:  这就是 原型对象
{
 constructor: ƒ doSomething(), //构造函数
  /* 这些又是这个构造函数里面的方法或者属性 
    arguments: null
    caller: null
    length: 0
    name: "doSomething"
    prototype: {constructor: ƒ} 构造函数的原型属性
     __proto__: ƒ ()*/

 __proto__: { //原型属性
     constructor: ƒ Object(),
     hasOwnProperty: ƒ hasOwnProperty(),
     isPrototypeOf: ƒ isPrototypeOf(),
     propertyIsEnumerable: ƒ propertyIsEnumerable(),
     toLocaleString: ƒ toLocaleString(),
     toString: ƒ toString(),
     valueOf: ƒ valueOf()
    }
 }   
-------------------------------  
function doSomething(){}  
doSomething.prototype.eat = "food" //doSomething函数的原型(prototype)属性对象添加eat的属性
var doSomeInstancing  =new doSomething() //创建doSomething函数的实例  通过new关键字来调用该函数,它返回这个函数的实例化对象给doSomeInstancing  
doSomeInstancing.prop = "add value";  //给对象doSomeInstancing添加一个“name为prop值为add value”的属性
console.log(doSomeInstancing);   //输出这个doSomeIntancing对象 结果现实这个对象有两个属性,一个是:prop: "add value" 另一个是:__proto__: Object
console.log(doSomething.prototype); //输出doSomething.prototype的值是一个对象{eat: "food",constructor: ƒ doSomething(), __proto__: Object
显然doSomeInstancing.__proto__属性与doSomething.prototype(构造函数的原型属性的值是相同)它们的值是相等的。(可以通过===来判断 __ptototype__为隐式原型)

bind()方法中的bind翻译过来就是捆绑、绑定之意,作用就是将函数绑定至某个对象中,倘若一个函数调用了bind()方法并传入一个对象作为参数,那么这个方法将返回新的函数。

function f(y){return this.x+y;} //待绑定的函数
var o = {x :1};//将要被绑定的对象
var g = f.bind(o); //将函数f绑定至对象o  相当于var o={x:1, f:function f(y){return this.x+y;}}
console.log(g(2));  //通过g(y)调用o.f(y) 输出3

bind()方法除了除了第一个实参之外,传入bind()的实参也会绑定至this.这种应用是一种常见的函数式编程技术,被称为柯里化(currying)

var sum = function(x,y){return x+y;}  
var succ = sum.bind(null,1);
succ(2)

最后

为了帮助大家让学习变得轻松、高效,给大家免费分享一大批资料,帮助大家在成为全栈工程师,乃至架构师的路上披荆斩棘。在这里给大家推荐一个前端全栈学习交流圈:866109386.欢迎大家进群交流讨论,学习交流,共同进步。

当真正开始学习的时候难免不知道从哪入手,导致效率低下影响继续学习的信心。

但最重要的是不知道哪些技术需要重点掌握,学习时频繁踩坑,最终浪费大量时间,所以有有效资源还是很有必要的。

最后祝福所有遇到瓶疾且不知道怎么办的前端程序员们,祝福大家在往后的工作与面试中一切顺利。

上一篇下一篇

猜你喜欢

热点阅读