- A+
所属分类:Web前端
函数声明的多种方式:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> </style> </head> <body> <script> // let str = new String('cyy'); // console.log(str); // let str2 = 'cyy2'; // console.log(str2.substr(0, 2)); // let func = new Function('title', 'console.log(title)'); // func('cyy'); // 字面量形式 // function func(name) { // console.log(name); // } // func('cyy'); // let func = function (name) { // console.log(name); // }; // func('cyy2'); let user = { name: null, // setName: function (name) { // this.name = name; // }, // getName() { // return this.name; // }, setName(name) { this.name = name; }, getName() { return this.name; }, } user.setName('cyy'); console.log(user.getName()); </script> </body> </html>
全局函数定义特点:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> </style> </head> <body> <script> // function func() { // console.log(111); // } // window.func(); // console.log(window.screenX); // function screenX() { // console.log(111); // } // console.log(window.screenX); // let不会挂载到window上,不属于全局 // var func1 = function () { // console.log(111); // } // window.func1(); // let func2 = function () { // console.log(222); // } // window.func2(); </script> </body> </html>
匿名函数与函数提升:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> </style> </head> <body> <script> // 这种情况不存在函数提升,匿名函数不存在函数提升 // 把一个匿名函数赋值给了变量 // let func1 = function () { // console.log(111); // } // func1(); ///这种情况存在函数提升 // func2(); // function func2() { // console.log(22); // } // function func() { // console.log(111); // } // func(); // var func = function () { // console.log(222); // } // func(); // 函数属于对象,引用类型的赋值 // var func = function () { // console.log(222); // } // console.log(func instanceof Object); // let func2 = func; // func2(); function sum(...args) { // reduce里箭头函数,也可以写成匿名函数 return args.reduce((a, b) => a + b); } console.log(sum(1, 3, 6, 9)); </script> </body> </html>
立即执行函数与块作用域解决冲突:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> </style> </head> <body> <script> // 立即执行函数,匿名函数自执行 // 防止污染全局 // (function (window) { // function show() { // console.log('show'); // } // window.func = { show }; // })(window); // window.func.show(); // show(); // 使用let的块级作用域解决问题 { function show() { console.log('show'); } window.func = { show }; } window.func.show(); </script> </body> </html>
形参与实参:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> </style> </head> <body> <script> // a,b是形参,1,2是实参;通常情况下参数个数是对应的 // function func(a,b){ // console.log(a,b); // } // func(1,2); // 形参个数大于实参时,多出来的形参值为undefined // function func(a, b, c) { // console.log(a, b, c); // } // func(1, 2); // 形参个数小于实参时,多出来的实参值会被忽略 function func(a, b) { console.log(a, b); } func(1, 2, 3, 4); </script> </body> </html>
默认参数的使用技巧:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> </style> </head> <body> <script> // function avg(total, year) { // year = year || 1; // return Math.round(total / year); // } // console.log(avg(2000)); // function avg(total, year = 1) { // return Math.round(total / year); // } // console.log(avg(2000)); // function sortArray(arr, type = 'asc') { // return arr.sort((a, b) => type == 'asc' ? a - b : b - a); // } // console.log(sortArray([11, 44, 22, 66, 33])); // console.log(sortArray([11, 44, 22, 66, 33], 'desc')); function sum(total, discount = 1, dis = 1) { return total * discount * dis; } console.log(sum(1000, 0.9, 0.7));// 折上折 </script> </body> </html>
函数参数与arguments:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> </style> </head> <body> <button id="btn">cyy</button> <script> // function func(val) { // return val <= 3; // } // let res = [1, 2, 4, 6, 8].filter(func); // console.log(res); // let i = 0; // setInterval(function () { // console.log(++i); // },1000); // let i = 0; // function func() { // console.log(++i); // } // setInterval(func, 1000); // document.getElementById('btn').addEventListener('click', function () { // alert(this.innerHTML); // }); // function func() { // alert(this.innerHTML); // } // document.getElementById('btn').addEventListener('click', func); // function sum() { // // 获取到所有传入的参数 // // console.log(arguments); // // let count = 0; // // for (let i = 0; i < arguments.length; i++) { // // count += arguments[i]; // // } // // return count; // // arguments是类数组,需要先转数组 // // return [...arguments].reduce((a, b) => a + b); // } function sum(...args) { return args.reduce((a, b) => a + b); } console.log(sum(1, 5, 23, 88)); </script> </body> </html>
箭头函数使用语法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> // 函数的简写形式,箭头函数 // let func = function() { // return 111; // } // let func = () => { // return 111; // } // let res = [1, 33, 66, 2, 8, 3].filter(function(item) { // return item < 10; // }); // console.log(res); // let res = [1, 33, 66, 2, 8, 3].filter(item => item < 10); // console.log(res); // let sum = [1, 2, 3, 4].reduce(function(a, b) { // return a + b; // }); // console.log(sum); // let sum = [1, 2, 3, 4].reduce((a, b) => a + b); // console.log(sum); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> // 函数的简写形式,箭头函数 // let func = function() { // return 111; // } // let func = () => { // return 111; // } // let res = [1, 33, 66, 2, 8, 3].filter(function(item) { // return item < 10; // }); // console.log(res); // let res = [1, 33, 66, 2, 8, 3].filter(item => item < 10); // console.log(res); // let sum = [1, 2, 3, 4].reduce(function(a, b) { // return a + b; // }); // console.log(sum); // let sum = [1, 2, 3, 4].reduce((a, b) => a + b); // console.log(sum); </script> </body> </html>
使用函数完成递归算法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> // 递归实现阶乘 // function factorial(num) { // if (num == 1) return 1; // return num * factorial(num - 1); // } // console.log(factorial(5)); function factorial(num) { return num == 1 ? 1 : num * factorial(num - 1); } console.log(factorial(5)); </script> </body> </html>
递归求和与点语法注意事项:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> // let sum = [1, 2, 3, 4].reduce((a, b) => a + b); // console.log(sum); let sum = function(...args) { // if (args.length == 0) return 0; // return args.pop() + sum(...args); return args.length == 0 ? 0 : args.pop() + sum(...args); } console.log(sum(1, 2, 3, 4)); // 参数中使用...语法,可以把接收到的所有参数变成一个数组 // function func(...args) { // console.log(args); // } // func(1, 2, 3, 4); </script> </body> </html>
递归实现倒三角:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> function star(num) { // if (num == 0) return ''; // // 会返回undefined,所以可以使用短路运算符简化操作 // // console.log(document.write('*'.repeat(num) + '<br/>')); // document.write('*'.repeat(num) + '<br/>') || star(--num);; return num ? document.write('*'.repeat(num) + '<br/>') || star(--num) : ''; } console.log(star(6)); </script> </body> </html>
递归附加参数使用技巧:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> let lessons = [{ title: 'title1', click: 99 }, { title: 'title2', click: 35 }, { title: 'title3', click: 66 }, ]; // function change(lessons, num = 100, i = 0) { // if (i == lessons.length) return lessons; // lessons[i].click += num; // // ++i 先递增,再赋值 // return change(lessons, num, ++i); // } // console.table(change(lessons)); // console.table(change(lessons, 50)); lessons = lessons.map(item => { return item.click += 100; }); console.table(lessons); </script> </body> </html>
什么是回调函数:、
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <button id="btn">cyy</button> <script> // 回调函数 // document.getElementById('btn').addEventListener('click', function() { // alert(this.innerHTML); // }) let arr = [1, 2, 3, 4]; arr.map((item, index, arr) => { // 改变原数据 arr[index] += 10; }); console.table(arr); let narr = arr.map(item => { // 生成新数据 item += 10; return item; }); console.table(narr); </script> </body> </html>
展开语法(点语法)正确使用方式:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> // let arr = [1, 2, 3]; // let [a, b, c] = [...arr]; // console.log(a, b, c); // let arr1 = [1, 2, 3]; // let [...arr2] = [1, 2, 3]; // console.log(arr1, arr2); // let [a, b, ...c] = [1, 2, 3, 4, 5]; // console.log(a, b, c); // function sum() { // // 类数组 // console.log(arguments); // } // sum(1, 2); // function sum(...args) { // // 展开语法,参数转数组 // console.log(args); // return args.reduce((a, b) => a + b); // } // console.log(sum(1, 2, 3, 4)); function sum(dis = 1, ...price) { // console.log(dis, price); let total = price.reduce((a, b) => a + b); return Math.round(total * dis); } console.log(sum(.9, 200, 33, 689)); </script> </body> </html>
函数与方法中this的不同:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> // 对象中的函数叫方法,类方法 // this指当前对象的引用 // let obj = { // name: 'cyy', // show() { // console.log(this.name); // } // } // obj.show(); // 全局中this指的就是windowd对象 // console.log(window); // console.log(this); // console.log(this == window); // 函数与方法中this指向不同 // let obj = { // name: 'cyy', // // show是方法,this指向当前对象 // show() { // // render是函数,this指向window对象 // function render() { // console.log(this); // console.log(this.name); // } // render(); // console.log(this); // console.log(this.name); // } // } // obj.show(); // User是构造函数创建的对象 // name是对象的属性 // show是对象的方法 // this指向当前对象 function User(name) { this.name = name; this.show = function() { // render是函数,this指向window function render() { console.log(this); } render(); return this.name; } } let cyy = new User('cyy'); console.log(cyy.show()); </script> </body> </html>
通过变量改变this指向:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> // let lesson = { // name: 'cyy', // lists: ['html', 'css', 'js'], // show() { // // console.log(this.name, this.lists); // const self = this; // 保存当前对象为self // return this.lists.map(function(item) { // // console.log(item); // // console.log(this); // 这里的this指向window // // self会随着作用域链向外部查找 // return `${self.name}--${item}`; // }) // } // } // console.table(lesson.show()); // 部分函数提供第二个参数,可以传入指代函数中使用的this // 比如map就可以 let lesson = { name: 'cyy', lists: ['html', 'css', 'js'], show() { return this.lists.map(function(item) { console.log(this); // 这里的this指向window return `${this.name}--${item}`; }, this); } } console.table(lesson.show()); </script> </body> </html>
箭头函数带来的this变化实例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <button>cyy</button> <button>cyy2</button> <script> // let func1 = function() { // console.log(111); // } // let func2 = () => { // console.log(222); // } // func1(); // func2(); // let lesson = { // name: 'cyy', // lists: ['html', 'css', 'js'], // show() { // console.log(this); // return this.lists.map(function(item) { // console.log(this); // 这里的this指向window // // return `${this.name}--${item}`; // }); // } // } // console.table(lesson.show()); // 箭头函数中,this指向父级作用域中的this // let lesson = { // name: 'cyy', // lists: ['html', 'css', 'js'], // show() { // console.log(this); // return this.lists.map(item => `${this.name}--${item}`); // } // } // console.table(lesson.show()); // let Dom = { // name: 'cyy', // bind() { // const button = document.querySelector('button'); // // console.log(button); // button.addEventListener('click', function() { // // this指向button // console.log(this); // console.log(this.innerHTML); // }); // button.addEventListener('click', () => { // // this指向当前对象DOM // console.log(this); // console.log(this.innerHTML); // }); // } // } // Dom.bind(); // let Dom = { // name: 'cyy', // bind() { // const button = document.querySelector('button'); // button.addEventListener('click', (event) => { // // this指向当前对象DOM // // event.target指向当前事件的元素 // console.log(this.name + event.target.innerHTML); // }); // } // } // Dom.bind(); // let Dom = { // name: 'cyy', // bind() { // const button = document.querySelector('button'); // const self = this; // button.addEventListener('click', function() { // console.log(self.name + this.innerHTML); // }); // } // } // Dom.bind(); // let Dom = { // name: 'cyy', // handleEvent(event) { // // event.target是传递过来的button // console.log(this.name + event.target.innerHTML); // }, // bind() { // const button = document.querySelector('button'); // const self = this; // // 把btn通过this传递 // button.addEventListener('click', this); // } // } // Dom.bind(); // let Dom = { // pre: 'cyy_', // bind() { // let buttons = document.querySelectorAll('button'); // buttons.forEach(item => { // //this是当前对象 // // console.log(this); // item.addEventListener('click', event => { // // console.log(event.target); // // console.log(this); // console.log(this.pre + event.target.innerHTML); // }) // }) // } // } // Dom.bind(); let Dom = { pre: 'cyy_', bind() { let buttons = document.querySelectorAll('button'); let self = this; buttons.forEach(function(item) { item.addEventListener('click', function(event) { console.log(self.pre + this.innerHTML); }) }) } } Dom.bind(); </script> </body> </html>
this的构造原理实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> // apply call bind // 构造函数 // function User(name) { // this.name = name; // } // let u = new User('cyy'); // console.log(u); // function User(name) { // this.name = name; // return { // a: 111 // }; // } // let u = new User('cyy'); // console.log(u); function User(name) { this.name = name; } let obj = { url: 'www.baidu.com' }; // this可以被改变,这里就把User里的this指向了obj User.call(obj, 'cyy'); console.log(obj); </script> </body> </html>
call与apply:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <button>cyy1</button> <button>cyy2</button> <script> // call和apply都可以改变this的指向,并且立即执行函数 // 区别在于传参方式的不同 // call是一个一个传,apply是数组形式传 // let user1 = { // name: 'cyy1' // }; // let user2 = { // name: 'cyy2' // }; // function User(pre, end) { // console.log(pre + this.name + end); // } // User.call(user1, 'cyy_', '_girl'); // User.apply(user2, ['hahaha_', '_end~']); // 在不传递参数的情况下,call和apply的用法和效果是一样的 // let buttons = document.querySelectorAll('button'); // for (let i = 0; i < buttons.length; i++) { // buttons[i].addEventListener('click', function(event) { // // 使用call改变this指向,指向被点击的按钮button // show.call(event.target); // // 使用apply改变this指向,指向被点击的按钮button // // show.apply(event.target); // }) // } // function show() { // console.log(this.innerHTML); // // 这里的this指向window // } console.log(Math.max(1, 2, 3, 7)); let arr = [2, 3, 7, 22]; console.log(Math.max(...arr)); // 把数组展开 console.log(Math.max.apply(Math, arr)); // this指向Math </script> </body> </html>
构造函数方法继承:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> function Request() { this.get = function(params) { console.log(params); // 将对象中的键提取成为一个数组Object.keys let get = Object.keys(params).map(key => `${key}=${params[key]}`).join('&'); let url = 'http://www.cyy.com/' + this.url + '/' + get; document.write(url + '<br/>'); } } function Article() { this.url = 'article/lists'; Request.call(this); } let a = new Article(); a.get({ id: 1, cate: 2 }); function User() { this.url = 'user/lists'; Request.call(this); } let u = new User(); u.get({ id: 1, role: 'admin' }); </script> </body> </html>
优雅的开发面板组件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> dt { background: orange; padding: 20px; border-bottom: 2px solid black; } dd { background: #ddd; margin-inline-start: 0; padding: 100px; } dt, dd { text-align: center; } </style> </head> <body> <dl> <dt>title1</dt> <dd>1</dd> <dt>title2</dt> <dd hidden="hidden">2</dd> </dl> <script> function panel(index) { let dds = document.querySelectorAll('dd'); console.log(dds); dds.forEach(dd => dd.setAttribute('hidden', 'hidden')); dds[index].removeAttribute('hidden'); } // document.querySelectorAll('dt').forEach((dt, index) => { // // console.log(dt); // dt.addEventListener('click', () => { // // call中没有用到this指向,所以可以传递null // panel.call(null, index); // }); // }); document.querySelectorAll('dt').forEach((dt, index) => { dt.addEventListener('click', () => panel.call(null, index)); }); </script> </body> </html>
bind原来是这么用的:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <button>cyy</button> <script> // call或者apply会立刻执行 // function show() { // console.log(this.name); // } // show.call({ // name: 'cyy' // }); // show.apply({ // name: 'cyy' // }); // // bind不会立刻执行,会生成一个新的函数,需要执行的时候再调用 // let func = show.bind({ // name: 'cyy' // }); // func(); // 函数的赋值是共用一个引用地址 // 而使用bind是复制一份,不再跟原来的共用一份 // function a() {} // let b = a; // console.log(a == b); // let c = a.bind(); // console.log(a == c); function sum(a, b) { console.log(this.f + a + b); } // call和apply是立即执行, 因此使用时必须直接传参 // sum.call({ // f: 100 // }, 2, 4); // sum.apply({ // f: 100 // }, [2, 7]); // sum.bind({ // f: 100 // }, 2, 7)(); // bind可以在绑定时传参,也可以在调用时传参 // sum.bind({ // f: 1 // })(2, 3); // // 绑定时参数足够了,那么调用时传的参数无效 // sum.bind({ // f: 1 // }, 3, 3)(2, 3); // // 绑定时参数不够,那么调用时按顺序补上 // sum.bind({ // f: 1 // }, 3)(11, 12); document.querySelector('button').addEventListener('click', function(event) { console.log(this.name + event.target.innerHTML); }.bind({ name: 'cyyyayaya~' }) ); </script> </body> </html>
漂亮的随机色效果:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <h1>CYY</h1> <script> function Color(elem) { this.elem = elem; this.colors = ['pink', 'lightblue', 'lightgreen', '#f5554a', '#ad80f6', '#8bc34a', '#ffef62', '#ff9800']; this.run = function () { let i = Math.floor(Math.random() * this.colors.length); this.elem.style.backgroundColor = this.colors[i]; console.log(i); }.bind(this); //使用bind改变this指向 } let c = new Color(document.body); c.run(); let h = new Color(document.querySelector('h1')); h.run(); </script> </body> </html>