函数的定义和调用
-
函数定义的三种方式
var fn2 = function(){} // 函数表达式 var fn3 = new Function(‘a’) // Function 关键字 fn.__proto__ fn.prototype // 函数也是对象, 底层是new构造函数的方式, 创建了一个函数对象, 所以它有__proto__属性, 既然是函数就有prototype属性
-
万物皆对象
// 万物皆对象 var num = 1; // new Number() var str = 'aa'; // new String() var flag= true; // new Boolean() var arr = []; //new Array() var obj = {}; // new Object() function fn1(){}; // new Function() console.dir(Function.prototype)
-
函数的几种调用方式 以及里面的this值
// 函数的不同调用方式决定了this 的指向不同 // 1. 普通函数 this 指向window function fn() { console.log('普通函数的this' + this); } window.fn(); // 2. 对象的方法 this指向的是对象 o var o = { sayHi: function() { console.log('对象方法的this:' + this); } } o.sayHi(); // 3. 构造函数 this 指向 ldh 这个实例对象 原型对象里面的this 指向的也是 ldh这个实例对象 function Star() {}; Star.prototype.sing = function() { } var ldh = new Star(); // 4. 绑定事件函数 this 指向的是函数的调用者 btn这个按钮对象 var btn = document.querySelector('button'); btn.onclick = function() { console.log('绑定时间函数的this:' + this); }; // 5. 定时器函数 this 指向的也是window window.setTimeout(function() { console.log('定时器的this:' + this); }, 1000); // 6. 立即执行函数 this还是指向window (function() { console.log('立即执行函数的this' + this); })();
改变函数内部的this指向
-
call,apply,bind
// call 方法 var o = { name: 'andy' } function fn(a, b) { console.log(this); console.log(a + b); }; fn.call(o, 1, 2); // 首先是调用函数, 其次是改变了函数里面的this指向, 原来的普通调用fn() 里面的this指向window, 现在指向o // call的应用--- 实现继承 function Father(uname, age, sex) { this.uname = uname; this.age = age; this.sex = sex; } function Son(uname, age, sex) { // 这一步操作 是将SON创建出来的实例对象son传入Father函数里面,并让this指向它; 这样实现了 son可以继承Father里面的几个属性 Father.call(this, uname, age, sex); } var son = new Son('刘德华', 18, '男'); console.log(son);
// apply 方法 var o = { name: 'andy' }; function fn(arr) { console.log(this); console.log(arr); // 'pink' }; // 作用和call一样, 但是参数传递的形式不一样, apply第二个参数必须是数组 fn.apply(o, ['pink']); // 3. apply 的主要应用 比如说我们可以利用 apply 借助于数学内置对象求数组最大值 // Math.max(); var arr = [1, 66, 3, 99, 4]; var arr1 = ['red', 'pink']; // var max = Math.max.apply(null, arr); var max = Math.max.apply(Math, arr); var min = Math.min.apply(Math, arr); console.log(max, min); // Math.max([1,2,3])
// 3. bind() 方法 绑定的意思 // 不会调用原来的函数, 会返回 原函数被改变this之后的 新函数 // 一般定义一个函数表达式 用 bind的返回值 给它赋值 var o = { name: 'andy' }; function fn(a, b) { console.log(this); console.log(a + b); }; var f = fn.bind(o, 1, 2); f(); // bind的应用, var btns = document.querySelectorAll('button'); for (var i = 0; i < btns.length; i++) { btns[i].onclick = function() { this.disabled = true; setTimeout(function() { this.disabled = false; }.bind(this), 2000); } }
严格模式
-
消除了js语法的一些不合理,不严谨之处;减少一些怪异行为;提高编译效率,增加运行速度;
-
开启严格模式; 分为脚本开启, 和函数开启严格模式两种情况
-
// 终极写法 ;(function(){ 'use strict'; })();
-
严格模式下的一些变化
- 变量必须先声明后使用
- 不允许删除变量
- 全局作用域中的函数普通调用 this 是 undefined
- 构造函数的调用必须使用new
- 定时中的this还是一样, 指向window
-
高阶函数
-
高阶就是把函数 当做参数 或者 返回值
// 1. 函数作为参数, 常见的回调函数 function eat(callback) { setTimeout(function () { console.log('吃完了') callback && callback() }, 1000) } //函数调用时,将这个匿名函数当做一个参数,一个实参,传递到这个函数里面,用形参callback接收 eat(function () { console.log('去唱歌') }) // 2. 函数作为返回值 // 求两个数的和, 只能传递一个参数 function getFun(n) { return function (m) { return n + m; } } var fn100 = getFun(100); // 这个fn100 就是getFun函数调用之后的返回值 console.log(fn100(1)) //这个时候计算的是 100 + 1 和