软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> Web前端 -> JavaScript函数和对象提高!!!!!! -> 正文阅读

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

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();

  • 图解作用域链 [img]
  • 分析作用域链

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  
Web前端 最新文章
10分钟
SSM框架SSM项目源码SSM源码下载java框架整合
javascript入门
JavaScript常用对象Array(2)
8.Smarty3:模版中的内置函数
表单脚本
iTextSharp5.0页眉页脚及Asp.net预览的实现
MVC基础学习—理论篇
JavaScript
http协议中get与post区别详解
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture
生肖星座 三丰软件 视频 开发 Android开发 站长 古典小说 网文精选 搜图网 美图 中国文化英文版 多播 租车 短信
2017-7-26 10:42:52
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --