函数进阶 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
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
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
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
变量名提升
JavaScript 是解释型的语言,但是它并不是真的在运行的时候完完全全的逐句的往下解析执行
func();
function func() {
console.log("Hello syl");
}
copy
相当于
function func() {
console.log("Hello syl");
}
func();
copy
再来看看变量声明的例子:
console.log(num);
var num = 10;
copy
相当于
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
上面的代码相当于:
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
复杂的闭包
function f1() {
var num1 = 6;
function f2() {
var num2 = 7;
}
console.log(num1 + num2);
}
f1();
copy
function f1() {
var num1 = 6;
function f2() {
var num2 = 7;
return num2;
}
return f2();
console.log(num1 + num2);
}
f1();
copy
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
学习时间 108分钟
操作时间 39分钟
按键次数 905次
实验次数 4次
报告字数 6805字
是否完成 完成