L40 2020-06-05 21:40:13 函数进阶
34 0

“Web开发基础”实验报告

函数进阶

函数进阶 1.谁调用 this,它就指向谁

<!DOCTYPE html>
<html>
<body>
<h2>函数进阶</h2>
<p>学习</p>

<script>
function foods(){}
foods.prototype = {
    price:"¥15",
    say:function(){
        console.log("My price is "+this.price);
    }
};

var apple = new foods();
apple.say();
var orange = new foods();
orange.say();
</script>
</body>
</html>
copy

image.png 2.call() 方法调用一个函数, 其具有一个指定的 this 值和分别地提供的参数(参数的列表)。语法为:

fun.call(thisArg, arg1, arg2, ...)
copy

使用 call() 方法调用函数并且指定上下文的 this。前面的例子可以改写成:

function foods() {}
foods.prototype = {
  price: "¥15",
  say: function() {
    console.log("My price is " + this.price);
  }
};

var apple = new foods();
orange = {
  price: "¥10"
};
apple.say.call(orange); // My price is ¥10
copy

在一个子构造函数中,你可以通过调用父构造函数的 call() 方法来实现继承。在控制台输入如下代码

function Father(name, age) {
  this.name = name;
  this.age = age;
}

function Son(name, age) {
  Father.call(this, name, age);
  this.hobby = "study";
}

var S1 = new Son("zhangsan", 18);
S1; // Son {name: "zhangsan", age: 18, hobby: "study"}
copy

3.apply() 方法与 call() 方法类似,唯一的区别是 call() 方法接受的是参数,apply() 方法接受的是数组。语法为:

fun.apply(thisArg, [argsArray]);
copy

使用 apply() 方法将数组添加到另一个数组

var array = ["a", "b", "c"];
var nums = [1, 2, 3];
array.push.apply(array, nums);
array; // ["a", "b", "c", 1, 2, 3]
copy
注:concat() 方法连接数组,不会改变原数组,而是创建一个新数组。而使用 push() 是接受可变数量的参数的方式来添加元素。使用 apply() 则可以连接两个数组。
copy

使用 apply() 方法和内置函数

var numbers = [7, 10, 2, 1, 11, 9];
var max = Math.max.apply(null, numbers);
max; // 11
copy
 注:直接使用 max() 方法的写法为:Math.max(7, 10, 2, 1, 11, 9);
copy

4.bind() 方法创建一个新的函数(称为绑定函数),在调用时设置 this 关键字为提供的值。并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项。语法为:

fun.bind(thisArg[, arg1[, arg2[, ...]]])
copy

创建一个简单的绑定函数例子

var bin = function() {
  console.log(this.x);
};
var foo = {
  x: 10
};

bin(); // undefined
var func = bin.bind(foo); // 创建一个新函数把 'this' 绑定到 foo 对象
func(); // 10
copy

图片描述

this.num = 6;
var test = {
  num: 66,
  getNum: function() {
    return this.num;
  }
};

test.getNum(); // 返回 66

var newTest = test.getNum;
newTest(); // 返回 6, 在这种情况下,"this"指向全局作用域

// 创建一个新函数,将"this"绑定到 test 对象
var bindgetNum = newTest.bind(test);
bindgetNum(); // 返回 66
copy
var newTest = test.getNum;
newTest();

// 上面这两行代码其实相当于:
var newTest(){
    return this.num;
}
// 所以 this 指向的是全局作用域,返回 6。
copy

5.在程序中,递归就是函数自己直接或者间接的调用自己。 例子:计算 1 到 10 之间的整数相加的和:

<!DOCTYPE html>
<html>
<body>
<h2>函数进阶</h2>
<p>学习</p>

<script>
function foo(n) {
  if (n == 0) {
    return 0;
  } // 临界条件
  else {
    return n + foo(n - 1);
  }
}
var a = foo(10);
document.write(a); // 55
</script>
</body>
</html>
copy

image.png 6.块级作用域 在 JavaScript 中是没有块级作用域的。比如:

{
  var num = 123;
  {
    console.log(num);
  }
}
console.log(num);
copy

函数作用域 JavaScript 的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的,不涉及赋值。来看个例子

function test() {
  var num = 123;
  console.log(num);
  if (2 == 3) {
    var k = 5;
    for (var i = 0; i < 10; i++) {}
    console.log(i);
  }
  console.log(k); // 不会报错,而是显示 undefined
}
test();
copy

image.png

function test() {
  var num = 123;
  console.log(num);
  if (2 == 2) {
    var k = 5;
    for (var i = 0; i < 10; i++) {}
    console.log(i);
  }
  console.log(k); // 不会报错,而是显示 undefined
}
test();
copy

image.png 变量名提升 JavaScript 是解释型的语言,但是它并不是真的在运行的时候完完全全的逐句的往下解析执行

func();

function func() {
  console.log("Hello syl");
}
copy

image.png 相当于

function func() {
  console.log("Hello syl");
}
func();
copy

再来看看变量声明的例子:

console.log(num);
var num = 10;
copy

image.png 相当于

var num; // 这里是声明
console.log(num); // 变量声明之后并未有初始化和赋值操作,所以这里是 undefined
num = 10; // 最终打印结果为 10
copy

函数同名的时候

func();
function func() {
  console.log("Hello syl");
}

func();
function func() {
  console.log("hi syl");
} // 最终结果打印了两次 hi syl
copy

上面代码相当于

function func() {
  console.log("Hello syl");
}
function func() {
  console.log("hi syl");
}
func();
func();
copy

函数变量同名的时候:

console.log(foo);
function foo() {}
var foo = 6;
copy

当出现变量声明和函数同名的时候,只会对函数声明进行提升,变量会被忽略。所以上面的代码相当于:

function foo() {}
console.log(foo);
foo = 6;
copy

再来看一种:

var num = 1;
function num() {
  alert(num);
}
num();
copy

image.png 上面的代码相当于:

function num() {
  alert(num);
}

num = 1;
num();
copy

看一个思考题:

var num = 3;
function foo() {
  console.log(num);
  var num = 4;
  console.log(num);
}
foo();
copy

上面的代码相当于:

var num = 3;
function foo() {
  var num; // 在函数顶部声明了局部变量,覆盖了函数体外同名的全局变量
  console.log(num); // 变量存在,但是它的值为 undefined
  num = 4; // 将其初始化赋值。
  console.log(num); //打印我们期望的值 4
}
copy

6.简单的闭包 在 JavaScript 中,使用全局变量是一个简单的闭包实例。比如:

var num = 3;
function foo() {
  console.log(num);
}
foo(); //打印 3
copy

image.png 复杂的闭包

function f1() {
  var num1 = 6;
  function f2() {
    var num2 = 7;
  }
  console.log(num1 + num2);
}
f1();
copy

image.png

function f1() {
  var num1 = 6;
  function f2() {
    var num2 = 7;
    return num2;
  }
  return f2();
  console.log(num1 + num2);
}
f1();
copy

image.png 7.在函数代码中,使用特殊对象 arguments,无需明确指出参数名,我们就能访问它们。第一个参数是 arguments[0],第二个参数是 arguments[1],以此类推。比如:

function foo() {
  console.log(arguments[0]);
  console.log(arguments[1]);
}
foo(2, 3); // 打印 2 3
copy

还可以用 arguments 对象检测函数的参数个数,引用属性 arguments.length 即可。来看一个遍历参数求和的例子:

function add() {
  var sum = 0;
  for (var i = 0; i < arguments.length; i++) {
    sum += arguments[i];
  }
  return sum;
}
add(); // 0
add(1); // 1
add(1, 2); // 3
add(1, 2, 3); // 6
copy

8.用 Function() 对象创建函数的语法如下:

var function_name = new Function(arg1, arg2, ..., argN, function_body)
copy

例子:

var add = new Function("a", "b", "console.log(a+b);");
var doAdd = add;
doAdd(2, 5); // 打印 7
add(2, 5); // 打印 7
copy

Function 对象的 length 属性

var add = new Function("a", "b", "console.log(a+b);");
console.log(add.length); // 打印 2
copy

Function 对象的方法

var add = new Function("a", "b", "console.log(a+b);");
add.valueOf();
add.toString();
copy

image.png

最新评论
暂无评论~