黑马程序员技术交流社区

标题: 【上海校区】函数进阶 [打印本页]

作者: jiang.dongqin    时间: 2018-5-18 09:39
标题: 【上海校区】函数进阶
本帖最后由 上海分校-小影 于 2018-5-18 11:06 编辑

函数进阶


一.定义函数的三种方式
1.函数声明
    fn();//函数声明可以先调用,在声明
    function fn(){
      console.log("这是函数声明")
    }

2.函数表达式
    var fn = function() {
      console.log("这是函数表达式");  
    }
    fn();//函数表达式必须先声明,再调用

3.构造函数Function
    //函数也是对象,可以使用Function构造函数new出来
    //相当于var fn = function(){}
    var fn = new Function();
   
    //语法:new Function(arg1,arg2,arg3..,body);
    // 1. 所有的参数都是字符串类型。
    // 2. 前面可以定义任意多个形参,最后一个参数是代码体。
    var fn = new Function("alert(1111)");
    fn();
   
    var fn1 = new Function("a1", "a2", "alert(a1+a2)");
    fn1(1,2);

二.eval函数--了解
eval的可以和new Function一样,执行字符串代码
注意:eval函数的功能非常的强大,但是实际使用的情况并不多。
- eval形式的代码难以阅读
- eval形式的代码无法打断点,因为本质还是还是一个字符串
- 在浏览器端执行任意的 JavaScript会带来潜在的安全风险,恶意的JavaScript代码可能会破坏应用

三.函数的四种调用模式
根据函数内部this的指向不同,可以将函数的调用模式分成4种

1. 函数调用模式
2. 方法调用模式
3. 构造函数调用模式
4. 上下文调用模式(借用方法模式)

    函数:当一个函数不是一个对象的属性时,我们称之为函数。
    方法:当一个函数被保存为对象的一个属性时,我们称之为方法。

函数调用模式

<font color="red">如果一个函数不是一个对象的属性时,就是被当做一个函数来进行调用的。此时this指向了window</font>
    function fn(){
      console.log(this);//指向window
    }
    fn();

方法调用模式
<font color="red">当一个函数被保存为对象的一个属性时,我们称之为一个方法。当一个方法被调用时,this被绑定到当前对象

    var obj = {
      sayHi:function(){
        console.log(this);//在方法调用模式中,this指向调用当前方法的对象。
      }
    }
    obj.sayHi();

构造函数调用模式
<font color="red">如果函数是通过new关键字进行调用的,此时this被绑定到创建出来的新对象上。</font>
    function Person(){
      console.log(this);
    }
    Person();//this指向什么?
    var p = new Person();//this指向什么?
总结:分析this的问题,主要就是区分函数的调用模式,看函数是怎么被调用的。

- 猜猜看:
    //分析思路:1. 看this是哪个函数的  2. 看这个函数是怎么调用的,处于什么调用模式
    //题目一:
    var age = 38;
    var obj = {
        age: 18,
        getAge: function () {
            console.log(this.age);
        }
    }
   
    var f = obj.getAge;
    f();//???
   
  
    //题目二
    var age = 38;
    var obj = {
      age:18,
      getAge:function () {
        console.log(this.age);//???
        function foo(){
          console.log(this.age);//????
        }
        foo();
      }
    }
    obj.getAge();
    obj["getAge"]();
   
   
    //题目三:
    var length = 10;
    var age = 18;
    function fn() {
        console.log(this.length);
    }
    var arr = [fn, "222"];
    fn();
    arr[0]();
   
    //题目四:
    // 面试题5:
    var length = 10
   
    function fn() {
        console.log(this.length)
    }
    var obj = {
        length: 5,
        method: function (fn) {
            fn()
            arguments[0]();
        }
    }

几种特殊的this指向
- 定时器中的this指向了window,因为定时器的function最终是由window来调用的。
- 事件中的this指向的是当前的元素,在事件触发的时候,浏览器让当前元素调用了function

上下文调用模式
上下文调用模式也叫方法借用模式,分为apply与call
使用方法: 函数.call() 或者 函数.apply()
call方法
call方法可以调用一个函数,并且可以指定这个函数的this指向

    //所有的函数都可以使用call进行调用
    //参数1:指定函数的this,如果不传,则this指向window
    //其余参数:和函数的参数列表一模一样。
    //说白了,call方法也可以和()一样,进行函数调用,call方法的第一个参数可以指定函数内部的this指向。
    fn.call(thisArg, arg1, arg2, arg2);

- 借用对象的方法
伪数组与数组
伪数组也叫类数组

1. 伪数组其实就是一个对象,但是跟数组一样,伪数组也会有length属性,也有0,1,2,3等属性。
2. 伪数组并没有数组的方法,不能使用push/pop等方法
3. 伪数组可以跟数组一样进行遍历,通过下标操作。
4. 常见的伪数组:arguments、document.getElementsByTagName的返回值、jQuery对象

    var arrayLike = {
      0:"张三",
      1:"李四",
      2:"王五",
      length:3
    }
    //伪数组可以和数组一样进行遍历

- 伪数组借用数组的方法
    Array.prototype.push.call(arrLike, "赵六");
    Array.prototype.join.call(arrLike, "-");

- 将伪数组转换成真数组
    var arr = Array.prototype.slice.call(arrLike);

apply方法
apply()方法的作用和 call()方法类似,只有一个区别,就是apply()方法接受的是一个包含多个参数的数组。而call()方法接受的是若干个参数的列表

call和apply的使用场景:
- 如果参数比较少,使用call会更加简洁
- 如果参数存放在数组中,此时需要使用apply

练习:
    1. 求数组的最大值和最小值
    2. 封装一个函数,能够打印出来所有的参数。

bind方法
bind()方法创建一个新的函数, 可以绑定新的函数的this指向

    //返回值:新的函数
    //参数:新函数的this指向,当绑定了新函数的this指向后,无论使用何种调用模式,this都不会改变。
    var newFn = fn.bind(window);


作者: wuqiong    时间: 2018-5-18 09:58





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2