第四章 函数
函数是功能实现的基本单元;一个函数的功能应当简单;编程就是把一组需求分解成一组函数和数据结构的技能。避免在一个函数内部实现多个功能。
使用字面量创建的函数链接到一个 Object.prototype ,使用函数表达式创建的函数,链接到一个Function.prototype,最终通过原型链链接到 Object.prototype.
函数在创建后,会具有一个prototype属性,它的值具有一个constructor属性就是该函数的对象。
函数可以被其他部分调用。
定义函数
函数的四部分:Function、函数名(匿名函数)、函数参数(parameters,形参,可选)、函数体。函数可以作为另一个函数的参数或者返回值。子函数可以访问内部的变量和参数,也可以访问外部父函数的变量和参数。函数的闭包。
调用函数
函数在调用过程中,除了传入的参数(括号中的参数),还默认传入this(this的值取决于函数的四种调用模式)和arguments(实参)。当实参大于形参,arguments会存储当前的函数全部实参。
arguments在函数参数不确定的时候可以使用(或者较多参数)arguments是一个伪数组,不具有数组的方法,这就是局限性。
let sum = function() {
let sum = 0;
for (let i = 0; i < arguments.length; i ++) {
sum += arguemnts[i];
}
return sum;
};
函数的四种调用模式
1、方法调用模式
函数作为对象的方法。this指向这个对象。通过this,可以使得内部函数访问对象中的公共方法和属性。
let myObject = {
value: 0,
increase = (inc) => {
this.value += typeof inc === 'number' ? inc : 1;
}
};
// 如果传入的参数是数值,函数的value属性叠加,不是数值就 + 1;
myObject.increase('test');
myObject.increase(2);
console.log(myObject.value === 3);
2、函数调用模式
一个函数不是作为对象的方法被调用,而是作为函数的形式被调用,此时 this 指向全局变量。
let myObject = {
value = 3;
}
myObject.double = function () {
let that = this;
let helper = function () {
that.value = add(that.value, that.value);
console.log(this); //全局变量
};
helper(); //以函数的形式调用函数 helper
}
myObject.double();
console.log(myObject.value);
3、构造器调用模式
使用new构造器创建函数,函数中的this绑定到新创建的对象上。(使用构造函数创建新对象是早期的方法,现在使用class关键字创建js中的class)。这种方法在最新的代码中不使用。
let Quo = function (string) {
this.status = sy=tring;
}
Quo.prototype.getStatus = function() {
return this.status;
}
let myQuo = new Quo("test");
myQue.getStatue();
4、Apply调用模式:this指向apply中的第一个参数;第二个参数是参数数组;(对比call方法的使用)。
let array = [3, 4];
let sum = add.apply(null, array);
console.log(sum === 7);
let statusObject = {
status: "OK"
};
let status = Quo.prototype.getStatus.apply(statusObject);
console.log(status === 'OK');
函数中遇到return就不会继续执行后面的代码了。
异常处理
异常:干扰函数正常执行过程中的事故(函数需要传入数值型参数,实际上传入字符串参数),当发现这样的事故,程序需要抛出一个异常。
throw语句会中断函数的执行;会抛出一个exception对象:具有异常的name属性和描述异常的message属性。
异常可以被try-catch捕获。产生异常的代码被try语句捕获,函数会跳转到catch语句执行。一个try语句只会有一个捕获所有异常的catch(一个try中只有一个catch)
如果解决异常的手段取决于异常的类型,异常检查器需要检查异常对宪法的name属性来确定异常的类型。
function add = (a, b) => {
if (typeof a !== 'number' || typeof b !== 'number') {
throw {
name: 'TypeError',
message: 'add function needs number'
};
}
return a + b;
}
function tryIt = function() {
try {
add("ten", 20);
}
catch (e) {
console.log(e);
}
}
递归
递归在dom树结构中使用较多;
let walk_the_dom = fucntion walk (node,func) {
// 把节点和处理的函数传入,对当前节点进行处理;
func(node);
node = node.firstChild;
while (node) {
// 遍历每一个子节点,并递归处理
walk(node, func);
node = node.nextSibling;
}
};
let getElementsByAttribute = function (att, value) {
let results = [];
walk_the_dom(document.body, fucntion(node) {
let actual = node.nodeType === 1 && node.getAttribute(att);
if (typeof actual === 'string' && (actual === value || typeof value !== 'string')) {
results.push(node);
}
});
return results;
}
作用域
es6中已经有块级作用域;
闭包
需要巩固
第五章 继承
需要巩固