08探索JS中的函数秘密
1 <!doctype html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" 6 content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>08探索JS中的函数秘密</title> 9 </head> 10 <body> 11 <!-- 12 1 普通使用方法 13 对象的方法中 this 指向该对象,对象方法中的函数中的 this 指向 window 对象。 14 对象方法中使用箭头函数时 this 指向父级作用域对象。 15 2 对象方法中使用事件监听函数 16 对象方法中事件监听使用箭头函数时 this 指向父级作用域对象。 17 对象方法中事件监听不使用箭头函数时 this 指向的是事件监听对象。 18 --> 19 20 <!--8.10 回调函数--> 21 <!--<button id="bt">点我</button>--> 22 23 <!--8.14.2 this在监听事件中的使用1-3--> 24 <!--<button>百度</button>--> 25 26 <!--8.14.3 this在监听事件中的使用-多个监听事件--> 27 <!--<button>百度</button>--> 28 <!--<button>新浪</button>--> 29 30 <!--8.16.4 bind和监听绑定事件一起使用--> 31 <!--<button>点我</button>--> 32 33 <script> 34 // 函数是对象,是一种引用类型 35 36 /*8.1 函数声明的多种方式*/ 37 /*8.1.1 function直接定义的函数*/ 38 // function name(a, b) { 39 // console.log(a + b); 40 // } 41 // name(5, 3); // 8 42 43 /*8.1.2 匿名函数赋值的方式定义的函数*/ 44 // let result = function (a, b) { 45 // console.log(a + b); 46 // }; 47 // result(5, 3); // 8 48 49 /*8.2 全局函数定义*/ 50 /*8.2.1 function直接定义的函数会放到window中*/ 51 // function baidu() { 52 // console.log("baidu.com"); 53 // } 54 // window.baidu(); // baidu.com 55 56 /*8.2.2 匿名函数赋值的方式定义的函数不会放到window中*/ 57 // let show = function sina() { 58 // console.log("sina.com"); 59 // } 60 // show(); // sina.com 61 // window.show(); // 报错 62 63 /*8.3 匿名函数与函数提升*/ 64 /*8.3.1 function直接定义的函数有变量提升的特性*/ 65 // name(5, 3); // 8 66 // function name(a, b) { 67 // console.log(a + b); 68 // } 69 70 /*8.3.2 匿名函数赋值的方式定义的函数没有变量提升的特性*/ 71 // result(5, 3); //报错 72 // let result = function (a, b) { 73 // console.log(a + b); 74 // }; 75 76 /*8.3.3 函数是对象,是一种引用类型*/ 77 // let result = function (a, b) { 78 // console.log(a + b); 79 // }; 80 // console.log(result instanceof Object); // true 81 // let name = result; 82 // name(3,5); // 8 83 84 /*8.4 立即执行函数与块作用域解决冲突*/ 85 /*8.4.1 立即执行函数*/ 86 // 立即执行函数不需要调用,直接执行 87 // (function(){ 88 // console.log("hello world!"); 89 // })(); // hello world! 90 91 /*8.4.2 立即执行函数的作用域*/ 92 // 立即执行函数中的函数由于作用域的原因不属于全局作用域 93 // (function(){ 94 // function baidu(){ 95 // console.log("baidu.com") 96 // } 97 // function sina(){ 98 // console.log("sina.com"); 99 // } 100 // })(); 101 // // 由于作用域的原因无法调用下面的函数 102 // baidu(); 103 104 /*8.4.3 提升立即执行函数中的函数作用域到全局*/ 105 // (function(window){ 106 // function baidu(){ 107 // console.log("baidu.com") 108 // } 109 // function sina(){ 110 // console.log("sina.com"); 111 // } 112 // window.lc = {baidu, sina}; 113 // })(window); 114 // lc.baidu(); // baidu.com 115 // lc.sina(); // sina.com 116 117 /*8.4.4 使用let块级作用域的特性限制函数的作用域*/ 118 // { 119 // let baidu = function () { 120 // console.log("baidu.com") 121 // }; 122 // let sina = function () { 123 // console.log("sina.com"); 124 // }; 125 // window.lc = {baidu, sina}; 126 // } 127 // lc.baidu(); // baidu.com 128 // lc.sina(); // sina.com 129 130 /*8.5 形参与实参*/ 131 // (a, b)是形参 132 // let sum = function(a, b) { 133 // return a + b; 134 // }; 135 // // (1, 2)是实参,实参数量和形参数量相对应 136 // console.log(sum(1, 2)); // 3 137 138 /*补充: 139 当形参数量大于实参数量时,多出的形参为undefined。 140 当实参数量大于形参数量时,多出的实参不被使用。 141 */ 142 143 /*8.6 默认参数的使用*/ 144 // let avg = function (total, year = 12) { 145 // return Math.round(total / year); 146 // } 147 // console.log(avg(1000,2)); // 500 148 // console.log(avg(1000)); // 83 149 150 /*8.7 函数参数与arguments*/ 151 /*8.7.1 函数参数*/ 152 // let name = function (a) { 153 // a[3] = 100; 154 // return a; 155 // }; 156 // let web = [1,2,3]; 157 // console.log(name(web)); // (4)[1, 2, 3, 100] 158 // console.log(web); // (4)[1, 2, 3, 100] 159 160 // let exec = function (a) { 161 // return a <= 3; 162 // } 163 // let arr = [1,2,3,4,5,6].filter(exec); 164 // console.log(arr); // (3)[1, 2, 3] 165 166 /*8.7.2 arguments*/ 167 // 基本语法 168 // let sum = function () { 169 // // 6 Arguments(6)[1, 2, 3, 4, 5, 6, callee: ƒ, Symbol(Symbol.iterator): ƒ] 170 // console.log(arguments.length,arguments); 171 // } 172 // sum(1,2,3,4,5,6); 173 174 // 求和运算 175 // let sum = function () { 176 // let total = 0; 177 // for (let i = 0; i < arguments.length; i++) { 178 // total += arguments[i]; 179 // } 180 // return total; 181 // }; 182 // console.log(sum(1,2,3,4,5,6)); // 21 183 184 // let sum = function (...args) { 185 // return args.reduce((a,b) => a + b); 186 // }; 187 // console.log(sum(1,2,3,4,5,6,7)); // 28 188 189 /*8.8 箭头函数使用语法*/ 190 // 递归函数、构造函数、事件处理不方便使用箭头函数,主要考虑到作用域和this关键字的问题。 191 // 匿名赋值函数声明 192 // let name = function () { 193 // return 1 + 2; 194 // }; 195 // console.log(name()); // 3 196 // 改写为箭头函数 197 // let name = () => { 198 // return 1 + 2; 199 // }; 200 // console.log(name()); // 3 201 202 /*8.9 使用函数完成递归算法*/ 203 // let factorial = function (num) { 204 // if (num===1){ 205 // return 1; 206 // } 207 // return num * factorial(num - 1); 208 // /* 209 // 阶乘调用顺序: 210 // return 3* factorial(3 -1); 211 // return 2* factorial(2 -1); 212 // return 1; 213 // 214 // return 3* 2* 1; 215 // return 2* 1; 216 // return 1; 217 // */ 218 // } 219 // console.log(factorial(3)); // 6 220 221 /*8.10 回调函数*/ 222 // 在某个时刻被其他函数调用的函数称为回调函数,比如处理键盘、鼠标事件的函数。 223 // document.getElementById("bt").addEventListener("click", function() { 224 // alert(this.innerHTML); 225 // }); 226 227 /*8.11 展开语法(点语法)正确使用方式*/ 228 /*8.11.1 放*/ 229 // let name = [1,2,3]; 230 // let [a,b,c] = [...name]; 231 // console.log(a,b,c); // 1 2 3 232 233 /*8.11.2 收*/ 234 // let [a, ...name] = [1,2,3,4]; 235 // console.log(a, name); // 1 (3)[2, 3, 4] 236 237 /*8.12 函数中this的使用*/ 238 // let obj = { 239 // site: "百度", 240 // show: function() { 241 // return this.site; 242 // } 243 // }; 244 // console.log(obj.show()); // 百度 245 246 // 全局中的this 247 // console.log(window === this); // true 248 249 // this表示当前对象的引用 250 // let obj = { 251 // site: "百度", 252 // show: function() { 253 // // 函数为对象的方法时 this 指向该对象 254 // console.log(this); // 对象方法中的 this 指向的为当前对象 obj。{site: '百度', show: ƒ} 255 // function render() { 256 // console.log(this); // 函数中的 this 指向的为 window 对象。Window{...} 257 // } 258 // render(); 259 // } 260 // }; 261 // obj.show(); 262 263 /*8.13 通过常量改变this指针*/ 264 /*8.13.1 示例1*/ 265 // let lesson = { 266 // site: "百度", 267 // list: ["js", "css", "html"], 268 // show: function () { 269 // // 将当前对象 lesson 赋值给名为 self 的常量 270 // const self = this; 271 // return this.list.map(function (value) { 272 // // 该函数中调用的 this 是 window 对象,通过向上找 self 调用当前对象 lesson。 273 // return `${self.site}-${value}`; 274 // }); 275 // }, 276 // }; 277 // console.log(lesson.show()); // (3)['百度-js', '百度-css', '百度-html'] 278 279 /*8.13.2 示例2*/ 280 // let lesson = { 281 // site: "百度", 282 // list: ["js", "css", "html"], 283 // show: function () { 284 // return this.list.map(function (value) { 285 // return `${this.site}-${value}`; 286 // },this); // 将当前 lesson 对象带入到 map 函数中,有些函数有该参数,有些函数没有该参数 287 // }, 288 // }; 289 // console.log(lesson.show()); // (3)['百度-js', '百度-css', '百度-html'] 290 291 /*8.14 箭头函数带来的this变化实例*/ 292 /*8.14.1 普通示例*/ 293 // let lesson = { 294 // site: "百度", 295 // list: ["js", "css", "html"], 296 // show: function () { 297 // return this.list.map((value) => { // 使用箭头函数时找父级的this,即lesson对象。 298 // return `${this.site}-${value}`; 299 // }); 300 // }, 301 // }; 302 // console.log(lesson.show()); // (3)['百度-js', '百度-css', '百度-html'] 303 304 /*8.14.2 this在监听事件中的使用1*/ 305 // let web = { 306 // site: "baidu.com", 307 // bind: function() { 308 // const button = document.querySelector("button"); 309 // console.log(button); // <button>百度</button> 310 // button.addEventListener("click", function() { // button.onclick=function(){}; 既对象的方法,所以this表示当前button对象 311 // console.log(this); // <button>百度</button> 312 // }); 313 // }, 314 // }; 315 // web.bind(); 316 317 /*8.14.2 this在监听事件中的使用2*/ 318 // let web = { 319 // site: "baidu.com", 320 // bind: function() { 321 // const button = document.querySelector("button"); 322 // console.log(button); // <button>百度</button> 323 // button.addEventListener("click", () => { // 使用箭头函数时找父级的this,即web对象。 324 // console.log(this); // {site: 'baidu.com', bind: ƒ} 325 // }); 326 // }, 327 // }; 328 // web.bind(); 329 330 /*8.14.2 this在监听事件中的使用3*/ 331 // 综合this在监听事件中的使用1-2 332 // let web = { 333 // site: "baidu.com", 334 // bind: function() { 335 // const button = document.querySelector("button"); 336 // console.log(button); // <button>百度</button> 337 // button.addEventListener("click", (event) => { // event参数对应实验1,箭头函数对应实验2。 338 // console.log(this); // {site: 'baidu.com', bind: ƒ} 339 // console.log(event.target); // <button>百度</button> 340 // console.log(this.site + event.target.innerHTML); // baidu.com百度 341 // }); 342 // }, 343 // }; 344 // web.bind(); 345 346 /*8.14.3 this在监听事件中的使用-多个监听事件*/ 347 // 示例1 348 // let web = { 349 // site: "站点", 350 // bind: function() { 351 // const buttons = document.querySelectorAll("button"); 352 // buttons.forEach((elem) => { 353 // elem.addEventListener("click", (event) => { 354 // console.log(this.site + event.target.innerHTML); // 站点百度 站点新浪 355 // }); 356 // }); 357 // }, 358 // }; 359 // web.bind(); 360 361 // 示例2 362 // let web = { 363 // site: "站点", 364 // bind: function() { 365 // const buttons = document.querySelectorAll("button"); 366 // const self = this; 367 // buttons.forEach(function (elem) { 368 // elem.addEventListener("click", function () { 369 // console.log(self.site + this.innerHTML); // 站点百度 站点新浪 370 // }); 371 // }); 372 // }, 373 // }; 374 // web.bind(); 375 376 /*8.15 构造函数*/ 377 /*8.15.1 默认返回值的构造函数*/ 378 // let user = function (name) { 379 // // this 默认是空的 380 // this.name = name; 381 // }; 382 // let lisi = new user("李四"); 383 // console.log(lisi); // user{name: '李四'} 384 385 /*8.15.2 指定返回值的构造函数*/ 386 // let user = function (name) { 387 // // this 默认是空的 388 // this.name = name; 389 // return {age: 14}; 390 // }; 391 // let lisi = new user("李四"); 392 // console.log(lisi); // {age: 14} 393 394 /*8.15.3 改变this的内容*/ 395 // let lisi = { 396 // name: "李四", 397 // }; 398 // let user = function (name) { 399 // this.name = name; 400 // } 401 // let web = {url: "baidu.com"}; 402 // user.call(web, "搜索引擎"); 403 // console.log(web); // {url: 'baidu.com', name: '搜索引擎'} 404 405 /*8.16 call、apply、bind的区别*/ 406 /*8.16.1 call、apply、bind的基本用法*/ 407 // let lisi = { 408 // name: "李四", 409 // }; 410 // let user = function (web, url) { 411 // console.log(web + url + this.name); 412 // } 413 // // 立刻执行 414 // user.call(lisi, "百度", "baidu.com"); // 百度baidu.com李四 415 // user.apply(lisi, ["新浪", "sina.com"]); // 新浪sina.com李四 416 // // bind不立刻执行,而是生成一个新的函数;可以在绑定的时候传参,也可以在调用的时候传参 417 // user.bind(lisi, "优酷","youku.com")(); // 优酷youku.com李四 418 419 /*8.16.2 bind生成一个新的函数*/ 420 // 普通函数 421 // let a = function () {}; 422 // let b = a; 423 // console.log(a===b); // true 424 425 // bind函数 426 // let a = function () {}; 427 // let b = a.bind(); 428 // console.log(a===b); // false 429 430 /*8.16.3 bind在绑定的时候传参,也可以在调用的时候传参*/ 431 // let sum = function (a, b) { 432 // console.log(a, b); 433 // return this.f + a + b; 434 // }; 435 // // 在绑定的时候传参 436 // let func = sum.bind({f:1},2,3); 437 // console.log(func()); // 2 3 6 438 // // 在调用的时候传参 439 // let func1 = sum.bind({f:4},5); 440 // console.log(func1(6,7)); // 5 6 15 441 442 /*8.16.4 bind和监听绑定事件一起使用*/ 443 // document.querySelector('button').addEventListener('click', function() { 444 // console.log(this); // {message: '欢迎!'} 445 // alert(this.message); // 欢迎! 446 // }.bind({message: "欢迎!"})); 447 448 </script> 449 </body> 450 </html>