JavaScript函数

JavaScript函数

1.1、JavaScript函数的定义

​ 函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块

​ 函数就是包裹在花括号中的代码块:

​ JavaScript 函数语法:

function 函数名(参数列表){
    这里是要执行的代码
}
<!-- 当我们点击这个按钮的时候,出来一个弹出框 -->
<!-- 
    click   鼠标单击事件

    注意: 
        在事件属性里面调用函数的话,必须加()
        
        什么叫事件属性?
            事件作为标签的一个属性存在的话
    -->
<button onclick="fn1()" type="button">点击我</button>

<script>
    /*
        js里面的函数: 函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。

        JS函数语法:
            function 函数名(参数列表){
                语句...;
                returen 返回值;
            }

        function js里面的关键字,用来定义js函数
        函数名: 自定义,要符合标识符规范
        我们可以在函数名的()里面定义参数列表
        如果函数需要返回值,那么我们在语句块里面通过return关键字来定义返回值
        JS函数在定义的时候,不需要返回值类型;
    */

    //比如我们在页面中很多地方都需要弹出框效果,那么我们就可以把弹出框代码放到函数里面,那么它就可以被重复使用了

    //函数本身不会自己运行,它需要调用才可以运行;
    function fn1(){
        //alert(任意数据类型参数)   警告框
        alert("我是警告框");
    }

    //调用函数
    //fn1();

    //fn1();
</script>

1.2、JavaScript声明式函数的应用

​ 函数的应用分为两步,一是先声明一个函数,再调用该函数。

声明函数:
1、声明无参函数语法
2、声明有参函数的语法
3、声明带有返回值的函数

1.2.1、JavaScript声明无参函数语法

​ 无参函数就是在函数名的小括号中不定义任何参数。

<script>
function sayHello(){
    alert("Hello World!");
}
</script>

1.2.2、JavaScript声明有参函数的语法

function functionName(varName1,varName...)
{
    函数代码块;
}

在这里插入图片描述

​ 上面的var1,var2就是参数,它代表一个不确定的值,这个值要参与函数代码块的运算,在调用函数时,可以给这些参数赋值。也可以在函数中定义多个参数,每个参数之间逗号 (,) 分隔:

myFunction(argument1,argument2,argument3,argument4)

​ 当声明函数时,参数相当于作为变量来声明。

​ 变量和参数必须以一致的顺序出现。第一个变量就是第一个被传递的参数的给定的值,以此类推。

1.2.3、JavaScript声明带有返回值的函数

​ 如果在执行完一块JavaScript代码后,也就是完成某一个业务逻辑后,需要返回一个具体的值,这就要函数返回值。
语法如下:

function myFunction(参数){
    函数代码块;
    return语句;
}

​ 示范:利用函数计算两个数相乘后的值,并返回。

//1、声明一个带参数的方法
function myFunction(a,b) {
         return a*b;
}
//2、调用带参的方法
var mul=myFunction(5,6);

在这里插入图片描述

需要注意的是,仅仅希望退出函数时 ,也可使用 return 语句。返回值是可选的:
function myFunction(a,b){
​ if (a>b){
​ return;
​ }
​ x=a+b
}
如果 a 大于 b,则上面的代码将退出函数,并不会计算 a 和 b 的总和。

1.2.4、JavaScript函数的调用

​ 在JavaScript中,调用函数时,如果没有返回值,就直接用函数方法名()调用。如果有参数,则必须给每个参数赋值,函数方法名(参数值),如果还有返回值,可以用一个变量来存储这个值。

​ 示范:

调用无参的函数:
sayHello();
调用有参的函数:
myFunction(“张三”,13);
调用有返回值的函数:
var mul=myFunction(5,6);

1.3、JavaScript形式参数和实际参数

​ 在JavaScript中,如果在使用带参的函数,必须分为两步:

​ 先是声明一个函数,写在声明函数中的参数叫做形式参数,简称形参,它代表一个不具体的值,也可以理解为就是声明了一个变量;

​ 而实际参数,简称实参,调用函数时,要给形参赋值,这个具体的值就是一个实际参数,实参就是表示一个具体的值。

//1、声明一个带参数的方法
function myFunction(name,age){
    alert("姓名" + name + ", 年龄" + age);
}
//其中name和age就是形参。

//2、调用带参的方法
myFunction("张三",13)

//"张三","13"就是一个实参。

​ 需要注意的是,同一个函数,形参和实参是一一对应的。

思考:如何区分实参和形参?
​ 1、出现的地方不一样,一个是在函数的声明中,一个出现在函数的调用中。
​ 2、代表的意义不一样,一个是声明一个变量,一个是该变量的值。

1.4、JavaScript局部变量和全局变量(函数作用域)

​ 变量从作用域的角度划分,分为两种:局部变量和全局变量。

1.4.1、JavaScript局部变量

​ 在JavaScript函数内部声明的变量是局部变量,所以只能在函数内部访问它,该变量的作用域是局部的。

​ 可以在不同的函数中使用名称相同的局部变量,因为只有声明过该变量的函数才能识别出该变量。只要函数运行完毕,局部变量就会被删除。

function sayHello(){
      //该变量声明在一个函数内部,name就是一个局部变量,
      //局部变量只可以在本函数内调用
      var  name="H5";
      alert("Hello "+name);
}

1.4.2、JavaScript全局变量

​ 在函数外声明的变量是全局变量,网页上的所有脚本和函数都能访问它。

//声明一个全局变量,任何函数都可以使用它
var  name="H5";
function sayHello(){
    alert("Hello "+name);
}
//调用函数
sayHello();

​ 需要注意的是,如果没有使用var声明变量,该变量将被自动作为全局变量声明。

​ 如这条语句:carname=“Volvo”;将声明一个全局变量 carname,即使它在函数内部声明。

1.4.3、JavaScript变量的生命周期

​ JavaScript 变量的生命期从它们被声明的时间开始。

​ 局部变量会在函数运行以后被删除。

​ 全局变量会在页面关闭后被删除。

1.4.4、JavaScript局部变量和全局变量的区别

1、声明位置不同
​ 局部变量声明在函数内部。全局变量声明在函数外部
2、作用域不一样
​ 局部变量只在某一个局部范围有效,比如函数内部。全局变量在整个页面有效,网页上的所有脚本和函数都能访问它。
3、生命周期不一样
​ 局部变量会在函数运行以后被删除,全局变量会在页面关闭后被删除

1.5、匿名函数

​ 匿名函数,就是没有名字的函数。

​ 一般的有名函数:

function  myFun( a,b ){
    console.info( a+b );
}
myFun( 10 , 30 );  // 输出40

匿名函数: 有关键词 function, 有小括号,有大括号,就是没有函数名。

function(a,b){
    console.info( a+b );
}

​ 想要执行它,怎么执行?没有名字,怎么调用?

方式一:把它放进一个变量里,这个变量就相当于一个函数名了。没有名字的匿名函数,变成有“名”函数了,我们把这种方式称之为函数字面量

var  myFun = function( a,b ){
    console.info( a+b);
};

myFun( 10,30 );

​ **方式二:**干脆不要名字,直接执行~!-- 这么做可以在内部形成局部变量和局部函数,防止全局污染。

​ 个人常用的直接执行匿名函数的方式!

(匿名函数)();

(匿名函数() );

//待议
(function(a,b){
    console.info( a+b );
})(10,30);

(function(a,b){
    console.info( a+b );
}(10,30));

​ 其他直接调用的方式显得比较怪异了。

// 在function前面加一元操作符号  
!function () { /* code */ } ();  
~function () { /* code */ } ();  
-function () { /* code */ } ();  
+function () { /* code */ } ();

// 在function前面添加 new 关键词
new function () { /* code */ }  
new function () { /* code */ } () // 如果需要传递参数,只需要加上括弧()

​ **方式三:**利用事件去调用。

var  btn = document.getElementById("btn");  // 找到页面某个标签

// 添加事件
btn.onclick = function(){
   console.info("你点了我!");
}

​ **方法四:**作为对象的方法调用

var  myObj = {
     name : "John",
     sayHello:function(){
         console.info("Hello,"+ this.name );
     }
};

myObj.sayHello();

​ **方法五:**作为另一个函数的参数。

​ **函数也可以作为另一个函数的参数的。**当然有名函数也可以做参数。

function myFun(fn){
    fn();
}

myFun( function(){
    console.info("这个匿名函数是个参数");
});

1.6、构造函数

​ 通过 new 函数名 来实例化对象的函数叫构造函数。任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数的主要 功能为 初始化对象,特点是和new 一起使用。new就是在创建对象,从无到有,构造函数就是在为初始化的对象添加属性和方法构造函数定义时首字母大写(规范)。

​ 对new理解:new 申请内存, 创建对象,当调用new时,后台会隐式执行new Object()创建对象。所以,通过new创建的字符串、数字是引用类型,而是非值类型。

1、常用的构造函数:

1. var arr = [];var arr = new Array();       的语法糖。
2. var obj = {}var obj = new Object();     的语法糖
3. var date = new Date();
4. ...

2、自定义构造函数:

<script>
    // 声明式函数: 通过function 函数名(){}  定义的函数,我们都称之为声明式函数
    // 匿名函数: 就是没有名字的函数,它同样通过function来定义;[它和声明式函数唯一的区别是没有函数名,其他都一致]
    // 函数字面量: 定义一个变量,然后给这个变量赋值匿名函数;
    // 通过  new 函数名    来实例化对象的函数叫构造函数。

    // 1. 构造函数名要大写
    // 2. 构造函数的作用就是用来创建对象的,
    // 3. 功能上: 普通函数是用来执行某个行为;构造函数是用来创建对象的
    // 4. 语法上: 基本没有差别
    // 5. 从函数体: 普通函数的函数体里面就是要执行的逻辑代码; 构造函数的函数体里面是用来初始化对象成员以及对象方法的;
    function Person(id,name,age) {
        //this关键字: 表示的当前对象
        this.id = id;   //对象的属性
        this.name = name;
        this.age = age;
        this.eat = function () {  //对象方法
            alert(this.name+"的吃饭行为");
        }
    }

    //直接通过函数名() 调用的是普通函数

    //使用构造函数,必须结合new来使用
    //Person()就算是构造函数,它也属于函数的一种
    var p1 = new Person(1001,"张三",12); //创建一个Person对象

    var p2 = new Person(1002,"李四",12);

    document.write("p1的name是:"+p1.name+"<br>");

    p1.eat();
</script>

1.7、回调函数

​ 我们先来看看回调的英文定义:A callback is a function that is passed as an argument to another function and is executed after its parent function has completed。

字面上的理解,回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调

​ 其实也很好理解对吧,回调,回调,就是回头调用的意思。主函数的事先干完,回头再调用传进来的那个函数。

​ 举一个别人举过的例子:约会结束后你送你女朋友回家,离别时,你肯定会说:“到家了给我发条信息,我很担心你。” 对不,然后你女朋友回家以后还真给你发了条信息。小伙子,你有戏了。其实这就是一个回调的过程。你留了个参数函数(要求女朋友给你发条信息)给你女朋友,然后你女朋友回家,回家的动作是主函数。她必须先回到家以后,主函数执行完了,再执行传进去的函数,然后你就收到一条信息了。

//定义主函数,回调函数作为参数
function A(callback) {
    callback();  
    console.log('我是主函数');
}

//定义回调函数
function B(){
    setTimeout("console.log('我是回调函数')", 3000);//模仿耗时操作  
}

//调用主函数,将函数B传进去
A(B);

//输出结果
我是主函数
我是回调函数

​ 上面的代码中,我们先定义了主函数和回调函数,然后再去调用主函数,将回调函数传进去。

​ 定义主函数的时候,我们让代码先去执行callback()回调函数,但输出结果却是后输出回调函数的内容。这就说明了主函数不用等待回调函数执行完,可以接着执行自己的代码。所以一般回调函数都用在耗时操作上面。比如ajax请求,比如处理文件等。

1.8、变量提升

1.8.1、执行环境

​ 执行环境定义了变量和函数有权访问的其他数据,决定了他们各自的行为。每个执行环境都有与之对应的变量对象(variable object),此对象保存着环境中定义的所有变量和函数。我们无法通过代码来访问变量对象,但是解析器在处理数据时会在后台使用到它。

全局执行环境:

​ 全局执行环境是最外围的一个执行环境,根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不同。在web浏览器中,我们可以认为它是window对象,因此所有的全局变量和函数都是作为window对象的属性和方法创建的。代码载入浏览器时,全局环境被创建,应用程序退出,如关闭网页或者浏览器时,全局执行环境被销毁。

函数执行环境:

​ 每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就被推入一个环境栈中,当函数执行完毕后,栈将其环境弹出,把控制权返回给之前的执行环境。

1.8.2、作用域

​ 在ES5中,JS只有两种形式的作用域:全局作用域和函数作用域。

​ 全局作用域: 全局对象的作用域,任意地方都可以访问到(如果没有被函数作用域覆盖)。在ES6中,新增了一个块级作用域(最近的大括号涵盖的范围),但是仅限于let方式申明的变量。

​ 函数作用域: 整个函数范围

1.8.3、变量提升(hoisting)

​ ES5 提升有变量提升和函数提升。

原则:

​ 1、所有声明都会被提升到作用域的最顶上;

​ 2、同一个变量声明只进行一次,并且因此其他声明都会被忽略;

​ 3、函数声明的优先级优于变量申明,且函数声明会连带定义一起被提升。

变量提升:

​ 把变量声明提升到函数的顶部,但是变量赋值不会提升。

console.log(a);
var a = 10;
//输出为undefined

//与上例等价
var a;
console.log(a);
a = 10;

​ 注意:变量未声明,直接使用,输出‘变量 is not defined’。

函数提升:

​ 函数提升会将函数声明连带定义一起提升。

​ 在JavaScript中函数的创建方式有三种:函数声明、函数表达式(函数字面量)、函数构造法(动态的,匿名的)。只有函数声明创建的函数会执行函数提升,字面量定义的函数(实质为变量+匿名函数)会执行变量提升。

test1();
function test1(){
    console.log("可以被提升");
}
test2();
var test2 = function(){
    console.log("不可以被提升");
}
console.log(test2);
var test2 = function(){
   console.log("不可以被提升");
}

函数和变量同时提升:

console.log(test3);
function test3(){console.log('func');}
var test3 = 'Mary';

1.9、防止全局污染

1.9.1、全局污染问题:

​ javaScript 可以随意定义保存所有应用资源的全局变量。但全局变量可以削弱程序灵活性,增大了模块之间的耦合性。在多人协作时,如果定义过多的全局变量 有可能造成全局变量冲突,也就是全局变量污染问题。

1.9.2、解决全局污染

// 方式1: 定义全局变量命名空间,只创建一个全局变量,并定义该变量为当前应用容器,把其他全局变量追加在该命名空间下。

//app就是一个全局变量,我们可以把app这个全局变量当成一个命名空间,然后把其他的所有全局变量都放在它下面;
var my={};  //唯一的全局变量
my.name={
    big_name:"zhangsan",
    small_name:"lisi"
};
my.work={
    school_work:"study",
    family_work:"we are"
};

// alert(my.name.small_name);

// 方式2: 利用匿名函数将脚本包裹起来

(function(){
    var temp = {};
    //把两个变量赋值给temp
    //temp.school_work = "study";
    //temp.small_name = "李四";
    small_name = "李四";
    temp.getName = function(){
        return small_name;
    }

    //把tmep赋值给全局变量test
    window.test = temp;
}())
// alert(test.getName());
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JTZ001

你的鼓励是我创作的最大动力?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值