函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。
函数声明的多种方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function logtitle(title) { console.log(title); } logtitle("6666");
let logmsg = function(msg) { console.log(msg); }; logmsg("888");
let obj = { name: null, setUserName(name) { this.name = name; }, getUserName() { return this.name; }, }; obj.setUserName("lisi"); console.log(obj.getUserName());
|
全局函数声明特点
声明全局函数时会把函数默认加载到 window 中,如果出现和已有的 window 方法重名,则原有方法会被新方法覆盖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function logname() { console.log("name"); } logname(); window.logname();
function innerWidth() { console.log("同名函数"); }
window.innerWidth();
let getusername = function() { console.log("name"); }; getusername();
|
获取屏幕宽度
1 2
| console.log(window.innerWidth);
|
监听屏幕大小改变事件
1 2 3 4 5 6 7
| window.addEventListener("resize", function(e) { console.log(e.currentTarget.innerHeight); console.log(e.currentTarget.innerWidth); });
|
匿名函数和函数提升
- 函数提升,如果使用变量定义了一个函数,则不能在定义该方法前使用该函数
- 没有用变量定义函数的话会存在函数提升,可以在页面任意地方使用
1 2 3 4 5 6 7 8 9 10 11 12 13
|
var show = function() { console.log("用变量定义函数"); }; show();
log(); function log() { console.log("全局函数"); } log();
|
立即执行函数和块机作用域
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| (function() { function show() { console.log("1.js.show()"); } window.js1 = { show }; })();
{ function show() { console.log("1.js.show()"); } window.js1 = { show }; }
|
默认参数的使用技巧
1 2 3 4 5 6 7 8 9 10
| function sortArray(array, type = "sort") { return array.sort((a, b) => { return type === "sort" ? a - b : b - a; }); }
console.log(sortArray([1, 5, 7, 9, 3, 2, 4, 5, 6]));
console.log(sortArray([1, 5, 7, 9, 3, 2, 4, 5, 6], "other"));
|
函数参数和 argument 参数
1 2 3 4 5 6 7 8 9 10 11 12 13
| function sum() { console.log(arguments); console.log([...arguments].reduce((a, b) => (a += b))); }
sum(1, 2, 3, 5, 4, 8, 7, 8, 4, 8);
function args(...arg) { console.log(arg); } args(5, 4, 8, 5, 4, 8, 5, 4, 5, 8, 6);
|
箭头函数
1 2 3 4 5 6 7 8 9 10 11
| function sum(array) { return array.reduce((a, b) => a + b); } console.log(sum([1, 2, 3, 4, 5, 6, 7, 8, 9]));
function filter(array) { return array.filter((item) => item <= 3).sort((a, b) => a - b); } console.log(filter([5, 2, 1, 4, 8, 6, 3, 5, 4, 8, 6]));
|
使用函数完成递归操作
- 递归函数必须接受参数。 (比如我要递归谁?)
- 在递归函数的定义初始,应该有一个判断条件,当参数满足这个条件的时候,函数停止执行,并返回值。(指定退出条件,否则就会死循环)
- 每次递归函数执行自己的时候,都需要把当前参数做某种修改,然后传入下一次递归。(每次循环在调用自己一次并传参)
- 当参数被累积修改到符合初始判断条件了,递归就停止了。(最后满足条件就退出)
- 一句话概括:所谓的递归函数就是在函数体内调用 n 次本函数。
1 2 3 4 5 6
| function digui(num) { console.log(num); return num == 1 ? 1 : num * digui(--num); } console.log(digui(5));
|
递归求和
1 2 3 4 5 6 7 8
| function sum(...args) { let pop = args.pop(); console.log(pop); console.log(args); return args.length === 0 ? 0 : pop + sum(...args); } console.log(sum(1, 2, 5, 5, 5, 5, 5));
|
递归实现倒三角形
1 2 3 4 5 6 7 8 9
| function state(num) { num ? document.write("*".repeat(num) + "<br>") + state(--num) : ""; } state(10);
|
回调函数
在某个时刻被其他函数调用的函数称为回调函数,比如处理键盘、鼠标事件的函数。
1 2 3 4 5
| document.querySelector("button").addEventListener("click", (item) => { item.toElement.style.fontSize = "200px"; alert("回调函数"); });
|
展开语法(点语法)的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
let arr1 = [1, 2, 3, 4, 5];
let [a1, ...a] = arr1; console.log(a1, a);
let arr2 = [1, 2, 3];
let [d, e, f] = [...arr2]; console.log(d, e, f);
console.log(...arr2);
function sum(toElement, ...price) { let total = price.reduce((a, b) => a + b); return toElement > 0 ? toElement * total : total; } console.log(sum(0.9, 20, 30, 40, 50));
let data = [ { name: "李四", id: "8", }, { name: "张三", id: "9", }, { name: "老王", id: "30", }, ]; let newdata = []; data.forEach((item) => { newdata.push(item.name); }); console.log(newdata.join("爱上了"));
|
方法和函数中的 this 指向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var age = 18; let user = { weight: "179kg", height: "188cm", getinfo: function() { console.log(this); console.log(this.age); function getwidth() { console.log(this); console.log(this.age); } getwidth(); return this.weight; }, }; console.log(user.getinfo());
|
通过常量改变 this 指向
1 2 3 4 5 6 7 8 9 10 11 12
| let user = { weight: "75kg", height: "188cm", lists: ["js", "css", "html"], show: function() { return this.lists.map(function() { console.log(this); }, this); }, }; console.log(user.show());
|
箭头函数带来的 this 指针变化
箭头函数本身没有 this 执行,他会往上下文找 this,通常说指向它的调用者。
1 2 3
| <button>张三</button> <a href="javaScript:;">标签一</a> <a href="javaScript:;">标签二</a>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| let obj = { site: "你好", show() { console.log(this); const that = this;
let fun_btn = document.querySelector("button");
fun_btn.addEventListener("click", function(ele) { console.log(this, "普通函数的this执行"); console.log(that.site + this.innerHTML); });
let arrows_btn = document.querySelector("button"); arrows_btn.addEventListener("click", (ele) => { console.log(this, "箭头函数的this指向"); console.log(this.site + ele.target.innerHTML); }); }, }; obj.show();
let newobj = { site: "这是", show() { const that = this; let alist = document.querySelectorAll("a"); alist.forEach(function(item) { console.log(this); item.innerHTML = that.site + item.innerHTML; item.addEventListener("click", function() { console.log(this); console.log(that); }); }); }, arrows() { let alist = document.querySelectorAll("a"); alist.forEach((item) => { item.addEventListener("click", (ele) => { console.log(this); console.log(ele.target); }); }); }, }; newobj.arrows();
|
this 的构造原理实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function getuser(msg) { console.log(this); this.name = msg; console.log(this); }
function callfun(msg) { this.name = "这是" + msg; console.log(this); } let obj = { age: "18", };
callfun.call(obj, "王五");
|
call 和 apply 改变 this 指向
- call()传递参数必须为逗号分隔传递,第一个参数是要指向的目标
- apply()传递参数必须是数组方式传递,第一个参数是要指向的目标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| function publicfun(age, height) { console.log(this); console.log(age + height + this.name); } let obj1 = { name: "李四", }; let obj2 = { name: "张三", };
publicfun.call(obj1, "18", "188cm");
publicfun.apply(obj2, ["18", "175cm"]);
let maxarray = [1, 2, 3, 4, 5, 6];
console.log(Math.max(...maxarray));
console.log(Math.max.apply(Math, maxarray));
console.log(Math.min.call(Math, ...maxarray));
|
构造函数方法继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| function pubilcfun() { this.url = "http://www.houdun/"; this.get = (parmas) => { let url = this.url + this.dominname + "?" + Object.keys(parmas) .map((item) => `${item}=${parmas[item]}`) .join("&"); document.write(url + "<hr>"); }; }
function fun1() { this.dominname = "bilibili"; pubilcfun.call(this); }
let user = new fun1(); user.get({ age: 18, name: "李四" });
function rolefn() { this.dominname = "baidu"; pubilcfun.apply(this); } let role = new rolefn(); role.get({ name: "管理员", asname: "账管员" });
|
bind 的使用
- bind call apply
- 三者相同点:都是用来改变 this 指向
- 不同点:
- call:传递参数要用逗号分割开来,会立即执行
- apply:传递参数以数组的形式传递,会立即执行
- bind:传递参数以逗号分开,和 call 相同,不会立即执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function user() { console.log(this.name); }
user.call({ name: "李四" });
user.apply({ name: "李四" });
user.bind({ name: "李四" }); user.bind({ name: "李四" })();
let button = document.querySelector("button"); button.addEventListener( "click", function(ele) { document.write(`${this.name}${ele.target.innerHTML}`); }.bind({ name: "zhangsan" }) );
|
形参和实参
1 2 3 4 5 6 7 8 9 10 11 12 13
| function sum(a, b) { return a + b; }
console.log(sum(5, 9));
function show(name = "张三", age = 18) { console.log(name, age); } show("李四", 15);
|