软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> Web前端 -> JavaScript函数和对象提高!!!!!! -> 正文阅读
Web前端 最新文章
10分钟
SSM框架SSM项目源码SSM源码下载java框架整合
javascript入门
JavaScript常用对象Array(2)
8.Smarty3:模版中的内置函数
表单脚本
iTextSharp5.0页眉页脚及Asp.net预览的实现
MVC基础学习—理论篇
JavaScript
http协议中get与post区别详解

[Web前端]JavaScript函数和对象提高!!!!!!

  2016-04-01 16:49:50

JavaScript函数和对象提高!!!!!!

主要内容介绍

  • 函数
    • 函数的概念
    • 函数的参数
    • 函数的返回值
    • 函数的作用域
    • 变量提升和函数提升
    • 函数参数传递方式
  • 对象
    • 什么是JavaScript对象
    • 创建对象的两种方式
    • 对象属性的基本操作
    • 创建自定义对象
    • 函数的4种调用方式(简单介绍)

一、函数

  • 函数小测验 函数复习测试题

1.1 函数基本概念

1.1.1 什么是函数


函数是定义一次但可以调用或执行任意多次的一段JavaScript代码。

  • 函数也叫做方法(了解概念)

    当一个函数在一个对象上被调用的时候,这个函数就叫做方法。 此时, 它的调用所在的对象就会作为函数的一个隐式的参数来传递。

// 函数
function func() {

}

var obj = {
    age: 18,
    getAge: function() {
        // 方法
    }
};

  • 函数的作用:封装代码,实现代码的复用

1.1.2 函数的重要性


函数对任何语言来说都是一个核心的概念。通过函数可以封装任意多条语句,而且可以在任何地方、任何时候调用执行。

函数是JavaScript的"一等公民"。

1.1.3 JavaScript中的函数能做什么?

  • 1 封装代码,实现代码复用(最基本的作用)
  • 2 作为数据来传递(回调函数)
  • 3 作为构造函数,创建对象
  • 4 作为一个作用域

1.2 函数的语法


// 函数声明的基本语法
// function关键字、funcname、小括号、大括号都是必需的
// 参数不是必需的
function funcname([arg1 [,arg2 [..., argn>) {
    statements
}

// 函数调用语法:函数名后面跟运算符()来调用
funcname();

  • 函数声明的注意点:

1 函数声明不能出现在类似:if语句中(尽管不报错,但这是糟糕的做法!如果这么做了,容易出现混乱)
2 funcname是要定义的函数名,必须是一个标识符(不要使用保留字或关键字),而不能是字符串或者表达式。
3 包含在小括号中的0个或多个参数,参数用逗号隔开
4 大括号内的是函数主体,包含了多条语句
5 return语句,可有可无。
6 函数命名推荐使用帕斯卡命名法,即第一个单词后的所有单词都以一个大写字母开始。

  • 练习: 求圆的面积(面积公式:S=πrr)

function calcCircularArea(radius) {
    return Math.PI * radius * radius;
}

console.log(calcCircularArea(10));

1.3 函数参数


//形参(函数声明时候的参数)
function f(a, b) {} // a,b是形参,占位用,函数定义时形参无值

//实参(函数调用时候的参数)
var x = 5,
    y = 6;
f(x, y); //x,y实参,有具体的值,会把x,y复制一份给函数内部的a和b

1.3.1 函数参数特点

  • 1 函数参数不区分类型
  • 2 函数的形参和实参个数不必相同

解释:
  1 JavaScript是弱类型的语言,可以用来保存任何类型的变量
  2 即便你定义的函数只接收两个参数,在调用这个函数时也未必一定要传递两个参数。可以传递一个、三个甚至不传递参数
  3 函数参数只能在函数体内使用
如果形参个数比实参个数多,那么多出来的参数值为:undefined(相当于声明变量,未初始化变量的值)
如果实参个数比形参个数多,那么多出来的参数将被忽略掉(不考虑 arguments)

  4 JavaScript中的函数没有重载的概念(相对于其他强类型的语言来说,
  例如:.Net、Java,并且这些语言中的函数,形参个数必须和实参个数相同)

补充:
    所谓的重载是指:方法的签名(函数名称)相同,参数顺序、个数、类型不同

// 具有一个参数的函数
function addNum(num) {
    return num + 10;
}
// 具有两个参数的函数
function addNum(num1, num2) {
    return num1 + num2;
}

// 此时调用 addNum 会执行哪个?
addNum(20 + 30);

//三个参数的f1把两个参数的f1覆盖,调用的是三个参数的f1
//证明JavaScript中没有重载

  • 函数调用的时候,会先计算参数的值
  • 函数参数是局部变量(只能在函数内部使用)

function add(num1, num1) {
    console.log(num1); // ??
}
add(1, 2);

  • 练习 1: 求2个数中的最大值,求3个数中的最大值

// 求两个数中的最大值
function getMaxNum(num1, num2) {
    return num1 > num2 ? num1 : num2;
}

console.log(getMaxNum(10, 5));

// 求三个数中的最大值
function getMaxNum1(num1, num2, num3) {
    return getMaxNum(getMaxNum(num1, num2), num3);
}

console.log(getMaxNum1(5, 8, 3));

  • 练习 2: 求一组数中的最大值

function getArrMaxNum(array) {
    var tempArr = array || [],
        i = 0,
        maxNum;
    if(tempArr.length === 0) {
        alert("请输入长度为1以上的数组");
        return;
    }

    maxNum = tempArr[0];
    for(; i < array.length; i++) {
        maxNum = array[i] > maxNum ? array[i] : maxNum; 
    }

    return maxNum;
}

console.log(getArrMaxNum([1, 3, 9, 10, 5, 2]));

1.3.2 arguments介绍

  • 作用:保存函数的实际参数
  • arguments仅在函数内部有效。
  • arguments是一个伪数组(即,只是与数组类似,并非一个真正的数组)

    因为可以使用方括号语法访问它的每一个元素(即第一个元素是 arguments[0] ,第二个元素是 argumetns[1] ,以此类推),使用 length 属性来确定参数长度。 没有传递值的命名参数将自动被赋予 undefined 值,跟定义了变量但又没有初始化一样。

function testArguments() {
  console.log("第一个参数为:" + arguments[0]);
}

testArguments("123"); // 第一个参数为:123

  • 练习:求多个数值中的最大值(非函数)

function getMaxNum() {
    var len = arguments.length,
        maxNum = arguments[0],
        i = 0;

    if(len === 0) {
        return maxNum;
    }

    for (; i < len; i++) {
        maxNum = arguments[i] > maxNum ? arguments[i] : maxNum;
    }

    return maxNum;
}

var maxNum = getMaxNum(1, 3, 2, 9, 5, 8);
console.log(maxNum); // ??

  • 思考:如何得到当一个函数定义时的该函数的参数数量?

1.3.3 函数的命名参数和arguments的关系

  • 面试题:

function b(x, y, a) {
    arguments[2] = 10;
    alert(a);
}
b(1, 2, 3); // ??

b(1, 2); // ??

函数的命名参数和arguments,它们的内存空间是独立的,而不是说读取这两个值会访问相同的内存空间。
只不过,它们的值会同步。
但是,如果调用时候有的参数未传入,那么通过修改 arguments 对应的值不会反映到命名参数中。

1.4 函数返回值

  • 使用 return 语句
  • 作用:使函数停止运行,并且把表达式的值(如果存在这样的表达式)返回给函数调用者。

注意点:
  1 如果return语句没有一个相关的表达式,它会返回undefined值
  2 如果函数不包含return语句,它就只执行函数体中的每条语句,然后返回给调用者undefined

// 有return语句,但是什么都不返回
function returnNothing() {
  console.log("函数被调用了");
  return;
}
var ret = returnNothing();
console.log(ret); // undefined

// 没有return语句
function noRetrun() {
  console.log("函数被调用了");
}
var ret = noRetrun();
console.log(ret); // undefined

1.5 函数表达式(函数直接量、函数字面量)

1.5.1 基本语法


// funcname 可以省略
var func = function funcname() {
  statements
};

  • 注意点:函数表达式中function后面的函数名,只能在函数内部使用;函数外部访问会报错!

var func = function fun () {
    console.log(fun); // 函数体
};

func();

console.log(fun); // Uncaught ReferenceError: fun is not defined

  • 练习:
    • 求阶乘(n! = 1 * 2 * 3 * ... (n-1)n)

var func = function factorial(num){
    if (num <= 1) {
        return 1;
    } else {
        return num * factorial(num - 1);
    }
};
console.log(func(4));

  • 练习:
    • 求斐波那契数列Fibonacci中的第n个数是多少 1 1 2 3 5 8 13 21...

var fibonacci = function fib(num) {
    var result = 0;
    if(num === 1 || num === 2) {
        return 1;
    }

    result = fib(num - 1) + fib(num - 2);

    return result;
};

console.log(fibonacci(3));

1.5.2 函数表达式与函数声明的异同

  • 不同点:
    • 1 语法不同,函数表达式被用作表达式,而不是用作语句,而且也无需指定函数名
    • 2 函数表达式中,function后面的funcname可以省略
    • 3 函数声明整个函数都会被提升,函数表达式只有变量名被提升
  • 相同点:
    • 除了上述语法不同外,其他用法都相同。

1.6 作为数据的函数(数组的sort方法)


JavaScript中的函数,不只是一种语法(即,声明函数或函数表达式),还可以是数据, 这意味着能够把函数赋给变量、存储在数组的元素中或作为对象的属性,甚至作为函数参数传递

function add(x) {
  return x + 10;
}

var ret = add(8); // 18
var otherAdd = add; // 把add赋值为变量 otherAdd
var otherRet = otherAdd(89); // 99


var arr = [];
arr[0] = function(x) {
  return x + 10;
};
arr[1] = 8;

arr[0](arr[1]); // 18

1.6 函数作用域

  • 问题分析:

// if() {} 语句块
var str = "window";
if(true) {
  var str = "if语句";
}
console.log(str); // ??

// for 循环语句块
for(var i = 0; i < 10; i++) {
  // ...
}
console.log(i); // ?
// 思考: 页面中有10个li,单击每个li弹出其索引号

// function 语句块
var str = "window";
function test() {
  var str = "local";
  console.log(str);
}
test(); // ??
console.log(str);


  • 结论:JavaScript函数形成了一个作用域

  • 面试题:

var num = 1;
function staticFunc() {
    console.log(num); // ??
}

function test() {
    var num = 2;
    staticFunc();
}
test();

1.6.1 词法作用域


JavaScript中的函数是通过词法来划分作用域的(而不是动态地划分作用域的)。
即,函数在定义它们的作用域运行(而不是在执行它们的作用域里运行)。

  • 定义和执行的区别:

// 定义指的是这个语句被解析执行的时候
function func() {

}
// 执行指的是这个函数被调用的时候
func();

  • 图解作用域链 
  • 分析作用域链

  • function func(num1, num2) {
      var sum = num1 + num2;
      return sum;
    }
    
    func(3, 6);
    
    // 复杂点的情况
    var age = 18;
    var name = "Tom";
    function getAge() {
      var age = 19;
      var str = "hello";
    
      function getStr() {
        var str = "world";
        console.log(age); // ??
        console.log(name); // ??
        console.log(str); // ??
      }
      getStr();
    }
    
    getAge();
    

    解释:
    当定义(声明)一个函数,当前的作用域链就保存起来,并且成为函数内部状态的一部分。
    在最顶级,作用域链仅由全局对象组成,而并不和词法作用域相关。
    然后,当定一个嵌套的函数时,作用域链就包含外围的包含函数。这意味着嵌套的函数可以访问包含函数的所有参数和局部变量。
    

    1.6.2 执行环境和作用域


    执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个
    与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。
    虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。
    
    全局执行环境是最外围的一个执行环境,在 Web 浏览器中,全局执行环境是 window 对象。
    所有全局变量和函数都是作为 window 对象的属性和方法创建的
    
    当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。作用域链的用途,是
    保证对执行环境有权访问的所有变量和函数的有序访问。
    
    作用域链本质上是一个指向变量对象的指针列表,它只引用但不实际包含变量对象。
    函数调用的执行过程:
        1. 设置作用域链
            当JavaScript的解释器调用一个函数,将此函数的作用域设置为定义函数的时候起作用的那个作用域链。
        2. 创建调用对象(其他名称:激活对象、活动对象),添加到作用域链的前端
            在作用域的前面添加一个新的对象:调用对象(call object),它用一个名为arguments的属性来初始化,
            即:局部变量、函数参数和Arguments对象、内部函数都在函数内的作用域中,放到了调用对象里面。
            这样就隐藏了作用域链更上层的任何同名的属性。
        3. 调用结束后,调用对象从作用域链中移除。(一般情况下)
            当没有涉及嵌套的函数的时候,作用域链是对调用对象的唯一引用。当对象从链中移除,也就是没有对它的引用了,
            最终通过对它的垃圾收集而完结。
    
    注意:this是一个关键字,而不是调用对象的一个属性,所以,this并不一定指的是函数自身。
    

    function func() {
        console.log("很平常的一个函数");
    }
    func();
    
    // 嵌套的函数
    function outerFunc(a, b) {
    
        function innerFunc(c) {
            console.log(a + "," + b + c);
        }
        innerFunc();
    }
    outerFunc();
    
    // 函数被作为返回值返回(了解)
    function foo() {
        var num = 10;
        return function() {
            console.log(num);
        };
    }
    
    var num = 20;
    // bar引用了 foo 的内部函数
    var bar = foo();
    bar(); // ??
    

    1.6.3 变量提升和函数提升

    • 面试题:

    // 1. 
    var foo = 1;
    function test(){
        console.log(foo); // ??
        var foo = 2;
        console.log(foo); // ??
    }
    test();
    

    • 分析题:

    // ??
    func();
    function func() {
      console.log("函数被调用了");
    }
    
    // ??
    func();
    var func = function() {
      console.log("函数被调用了");
    };
    

    • 变量提升
      • 1 使用 var 声明的变量会自动被添加到最接近的环境中
      • 2 在函数内部,最接近的环境就是函数的局部环境
      • 3 未声明就使用的变量会成为全局变量(糟糕的做法,不推荐!!!)
      • 4 建议在初始化变量之前,一定要先声明
    • 函数提升

    每个作用域都会进行提升操作。
    包括变量和函数在内的所有声明都会在任何代码被执行前先被处理。
    
    函数声明会被提升,但是函数表达式却不会被提升。
    函数会首先被提升,然后才是变量
        如果函数声明和变量声明的名称相同,此时,var foo; 尽管出现在 function foo(){}
        的声明之前,但它是重复的声明(因此var foo;被忽略了),因为函数声明会被提升到普通变量之前。
        如果是 var foo = 123; 即:声明同时初始化了,那么foo的值为123。
    

    1.6.5 模仿块级作用域

    • 立即执行的函数表达式(高大上的名字)
      • 立即执行:声明了就立即调用执行
      • 函数表达式
    • 注意:函数声明后面不能跟圆括号。然而,函数表达式的后面可以跟圆括号。

    // 第一个小括号的作用是将函数声明转化为函数表达式
    (function() {
        // 这里是模拟出来的块级作用域
    })();
    
    // 另外一种形式(了解)
    (function(){
    
    }());
    

    1.7 函数参数传递方式


    // 基本数据类型
    function add(num) {
        num = num + 10;
        return num;
    }
    
    var count = 20;
    var result = add(count);
    console.log("count的值为:" + count); // ??
    console.log("result的值为:" + result); // ??
    
    // 复杂数据类型
    // 1.
    function setAge(obj) {
        obj.age = 18;
    }
    
    var person = new Object();
    person.age = 30;
    
    setAge(person);
    console.log(person.age); // ??
    
    // 2.
    function setName(obj) {
        obj.name = "小明";
        obj = new Object();
        obj.name = "小红";
    }
    
    var person = new Object();
    person.name = "Jack";
    
    setName(person);
    console.log(person.name); // ??
    

    • JavaScript中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参 数,就和把值从一个变量赋值到另一个变量一样。

    • 参数实际上是函数的局部变量,那么这些局部变量(包括:函数参数、函数内部声明的变量), 在函数执行完毕后会被立即销毁掉。

    • 练习:输入某年某月某日,判断这一天是这一年的第几天?
      • 闰年计算方法:能被4整除并且不能被100整除,或者能被400整除
      • 2月到底是28天还是29天?
      • 1-12月的天数?
        案例:一年中的第几天

    二、对象

    • JavaScript中如何创建对象?

    // 创建一个对象
    var obj = new Object();
    // 给对象设置属性
    obj.name = "小明";
    obj.age = 18;
    

    2.1 什么是JavaScript对象


    JavaScript中的对象:无序属性的集合,其属性可以包含基本值、对象或者函数。
    严格来讲,这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,
    而每个名字都映射到一个值。
    

    • 对象和基本类型的区别:

    对象与数字、字符串、布尔值这样的数据类型不同,它们不是表示一个单个的值,而是值的集合。
    对象是已命名值的一个集合。
    
    数字、字符串、布尔值是简单数据类型
    对象是复杂数据类型
    

    • 函数也是对象

    2.2 如何创建JavaScript对象

    2.2.1 创建对象的两种方式

    • 1、构造函数方式
    • 2、对象字面量

    2.2.2 创建对象的两种方式对比

    • 方式一:使用构造函数创建对象

    // 使用 new 操作符,后面跟 Object构造函数调用,来创建对象
    // 此时,返回值:obj,就是新创建出来的对象
    var obj = new Object();
    // 给对象添加属性
    obj.name = "静静";
    obj.age = 18;
    obj.getName = function () {
        return this.name; // 静静
    };
    

    • 方式二:使用对象字面量(推荐)

    // 语法规则
    var person = {
        // 属性名: 属性的值
        // 使用逗号来分隔不同的属性(如果当前属性后面还有其他属性的话)
        name: "Nicholas",
        age: 18
    };
    
    // 创建对象设置属性
    var person = {
        name: "加引号的属性名称",
        0: "属性名为数值类型,那么这里的数值属性名会自动转换为字符串"
    };
    
    // 创建一个空对象,没有任何属性
    var person = {};
    

    • 对象字面量的说明:

        1. 对象字面量是对象定义的一种简写形式,目的在于简化创建包含大量属性的对象的过程。
        2. 语法规则中,左边的花括号({)表示对象字面量的开始,因为它出现在了表达式上下文中。
        3. 对象字面量的属性名,可以不加引号 也可以加引号(单引号或者双引号都可以)
    

    2.3 对象的基本操作

    2.3.1 属性的设置


    // 创建一个空对象
    var obj = {};
    // 使用点运算符(.)来设置属性的值
    obj.name = "这是name属性的值";
    obj.age = 18; // 给age属性设置值:18
    // 使用方括号[]来设置属性的值,注意:要访问的属性是字符串的形式或者是变量
    obj["font-size"] = "30px";
    

    2.3.2 属性的读取


    // 获取属性的两种方式
    console.log(obj.name);
    console.log(obj["name"]);
    

    区别:
        1. 都可以用来设置或者获取对象的属性。
        2. 方括号([])可以通过变量来访问属性。
        3. 属性名中包含会导致语法错误的字符,或者属性名使用的是关键字和保留字,使用方括号表示法。
           例如:obj["first name"],由于"first name"中包含一个空格,所以不能使用点表示法来访问它。
                 然后,属性名中是可以包含非字母非数字的,这时候就可以使用方括号表示法来访问它们。
        4. 除非必须使用变量来访问属性,否则推荐使用点表示法。
    

    2.3.3 属性的遍历

    • 如何获取对象的一个属性?
    • 如果要获取对象的所有属性,怎么获取?
      • for-in

    var obj = {
        name: "明哥",
        age: 18,
        weight: 50
    };
    
    for(var ob in obj) {
        // ob 为属性名
        // obj[ob] 为属性名对应的值
        console.log("属性 " + ob + " 的值为:" + obj[ob]);
    }
    

    2.4 如何创建自定义对象

    • 1 使用函数,函数名首字母大写(为了区分普通函数)(此时的函数叫做:构造函数)
    • 2 使用this关键字

    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    
    var p = new Person("猴哥", 18);
    console.log(p.name);
    console.log(p.age);
    

    • new 操作符的作用
      • 1 创建一个对象
      • 2 将构造函数的作用域赋给新对象, 所以this == p
      • 3 执行构造函数,为对象设置属性
      • 4 返回新对象

    额外补充

    把对象属性用作参数(了解)

    • 问题:有一个函数有10个参数,那此时有什么痛点?
      • 1 函数定义或者调用的时候,就要写一堆的参数,十分繁琐
      • 2 函数调用的时候,要记住正确的参数调用顺序

    // 声明一个包含10个参数的函数
    function moreArgsFunc(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10) {
        // 函数处理
    }
    // 调用函数
    moreArgsFunc(true, false, 1, 0, 1, "string", "number", " ", null, null);
    

    • 解决方式:把对象作为函数的参数

    function objArgsFunc(obj){
        // 函数处理
        // 使用参数 obj.arg1
    }
    
    obj({
        /*arg1: true,
        arg2: false,
        ...*/
    });
    

    函数的4种调用方式(理解)

    • 1 作为函数调用
    • 2 作为对象的方法调用
    • 3 作为构造函数调用
    • 4 使用call或者apply调用

    // 1 作为函数调用
    function func() {
        this.age = 18;
        console.log(this.age);// this 指向 window
    }
    func(); 
    
    // 2 作为对象方法调用
    var obj = {
        name: "functionName",
        age: 19,
        getName: function() {
            console.log(this.name);// this指向obj
        }
    };
    obj.getName(); 
    
    // 3 作为构造函数调用
    function Person(name) {
        this.name = name;// this 指向新创建出来的对象p
    }
    var p = new Person("小明"); 
    console.log(p.name);
    
    // 4 使用call或者apply调用
    // call和apply的区别:参数不同
    // call(上下文, arg1, arg2, ...)
    // apply(上下文,[arg1, arg2, ...])
    func.call(obj); // this 指向传入的参数:obj

    上一篇文章      下一篇文章      查看所有文章
    2016-04-01 16:48:17  
    360图书馆 论文大全 母婴/育儿 软件开发资料 网页快照 文字转语音 购物精选 软件 美食菜谱 新闻中心 电影下载 小游戏 Chinese Culture
    生肖星座解梦 三沣玩客 拍拍 视频 开发 Android开发 站长 古典小说 网文精选 搜图网 天下美图 中国文化英文 多播视频 装修知识库
    2017-1-20 11:49:42
    多播视频美女直播
    ↓电视,电影,美女直播,迅雷资源↓
    TxT小说阅读器
    ↓语音阅读,小说下载,古典文学↓
    一键清除垃圾
    ↓轻轻一点,清除系统垃圾↓
    图片批量下载器
    ↓批量下载图片,美女图库↓
      网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --