js基础深入总结
- 便于阅读和交流
4.3 如何定义函数?
- 函数声明
- 表达式
- 实例化函数对象
4.4 函数的2种角色
- 函数: 通过()使用
- 对象: 通过.使用 ==> 称之为: 函数对象
4.5 如何调用(执行)函数?
- test()
- new test()
- obj.test()
- test.call/apply(obj)
/*
编写程序实现以下功能需求:
1. 根据年龄输出对应的信息
2. 如果小于18, 输出: 未成年, 再等等!
3. 如果大于60, 输出: 算了吧!
4. 其它, 输出: 刚好!
*/
function showInfo (age) {
if(age<18) {
console.log('未成年, 再等等!')
} else if(age>60) {
console.log('算了吧!')
} else {
console.log('刚好!')
}
}
//多次调用
showInfo(17)
showInfo(22)
/*函数也是对象*/
function fn() {
console.log('fn()')
}
console.log(fn instanceof Object) // true 函数是Object类型的实例
console.log(fn.prototype) // 有属性
console.log(fn.call) // 有方法
fn.xxx = 'abc' // 可以添加属性
fn.yyy = function () { // 可以添加方法
}
/*
函数的2种角色
1. 函数: 通过()使用
2. 对象: 通过.使用 ==> 称之为: 函数对象
*/
fn() // fn是函数
fn.yyy() // fn是函数对象
4.6 回调函数
-
回调函数一般指的是:一个函数A被作为参数传递给另一个函数B,回调函数B在A中被调用
-
还有其他类型的回调函数
- 你定义的
- 你没有直接调用
- 但最终它执行了(在特定条件或时刻)
-
常见的回调函数?
- DOM事件函数
- 定时器函数
- ajax回调函数(后面学)
- 生命周期回调函数(后面学)
//1. DOM事件回调函数
var btn = document.getElementById('btn')
btn.onclick = function () {
alert(this.innerHTML)
}
//2. 定时器回调函数
setInterval(function () {
alert('到点啦!')
}, 2000)
IIFE
-
理解
- 全称: Immediately-Invoked Function Expression 立即调用函数表达式
- 别名: 匿名函数自调用
-
作用
- 隐藏内部实现
- 不污染外部命名空间
(function (i) {
var a = 4
function fn() {
console.log('fn ', i+a)
}
fn()
})(3)
5. 函数中的this
5.1 this是什么?
- 一个关键字, 一个内置的引用变量
- 在函数中都可以直接使用this
- this代表调用函数的当前对象
- 在定义函数时, this还没有确定, 只有在执行时才动态确定(绑定)的
5.2 this的指向方式
-
默认绑定 :常用的函数调用类型:独立函数调用
可以把这个规则看作是无法应用其他规则的时候 默认的规则,基本指向的是window
function foo() { console.log(this); } foo(); //window var obj = { do: function () { foo(); //foo是直接使用不带任何修饰的函数引用进行调用,因此只能使用默认绑定 规则 }, }; obj.do(); -
隐式绑定
当函数引用有上下文对象的时候(obj),隐式绑定规则会把函数中的this绑定到这个上下文对象上
function foo() { console.log(this.a); } var obj = { a: 2, foo: foo, // }; obj.foo(); // //当foo调用的时候,它的落脚点确实是指向的obj对象,当函数引用有上下文对象的时候(obj),隐式绑定规则会把函数中的this绑定到这个上下文对象上 -
隐式绑定可能会出现隐式丢失的问题 :被隐式绑定的函数,会丢失了绑定对象
function foo() { console.log(this.a); } var obj = { a: 2, foo: foo, }; var fn1 = obj.foo; var a = "hello"; fn1(); //hello 虽然fn1是obj.foo的一个引用,但是实际上它的引用是foo函数本身,因此fn1其实是一个不带任何修饰的函数调用,属于默认绑定 // function foo() { console.log(this.a); } function doFoo(fn) { fn(); //传参也是隐式赋值,所以传递函数也是隐式赋值,赋值的是foo函数本身 } var obj = { a: 2, foo: foo, }; doFoo(obj.foo); -
显式绑定
function foo() { console.log(this.a); } var obj = { a: 2, }; foo.call(obj); //2 //通过call 调用foo时,把foo的this强制的绑定给了obj上 -
new绑定
构造函数只是一些使用new
操作符被调用的函数,使用new调用函数的时候,会构造一新的对象,这个时候 就把新的对象绑定给了函数的this上
function Foo(a) { this.a = a; } var bar = new Foo(2); console.log(bar.a); //2
5.3 怎么判断this指向
-
函数是否在new中调用,如果是的话,this绑定的是新创建的对象
-
函数是否通过call、apply(显示绑定)调用,如果是,则this绑定的是执行的对象
-
函数是否在某个上下文对象中调用(隐式绑定),如果有,则this绑定在这个上下文对象上
-
如果以上都不是 则默认绑定 执行window
//obj.f在上面代码中,obj.f表示在obj对象上调用f函数,则调用对象为obj,此时this就指向obj,this.x就等于obj.x,即返回结果为2
//若把obj.f赋值给变量f1,然后在全局上下文中调用们函数,则f函数体的运行环境在全局上下文中执行,此时this就指向 window, this.x就等于 window.x,即返回结果为1
var x = 1;
var obj = {
f:function(){
console.log(this.x)
},
x:2
}
obj.f();
var f1 = obj.f;
f1();
6 call apply 与 bind
在JavaScript中,call、apply和bind是Function对象自带的三个方法。
这三个函数的存在意义是改变函数执行时的上下文,再具体一点就是改变函数运行时的this指向。
6.1 call()
-
call()方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法 -
当调用一个函数时,可以赋值一个不同的
this对象。this引用当前对象,即call方法的第一个参数。 -
通过
call方法,你可以在一个对象上借用另一个对象上的方法 -
语法
fun.call(thisArg[, arg1[, arg2[, ...]]])- thisArg: 在fun函数运行时指定的
this值。需要注意的是下面几种情况- 不传,或者传
null,undefined, 函数中的this指向window对象 - 传递另一个函数的函数名,函数中的
this指向这个函数的引用,并不一定是该函数执行时真正的this值 - 值为原始值(数字,字符串,布尔值)的
this会指向该原始值的自动包装对象,如String、Number、Boolean - 传递一个对象,函数中的this指向这个对象
- 不传,或者传
- arg1...
- fun函数所需要的参数,逗号间隔
- thisArg: 在fun函数运行时指定的
-
案例:
function a(){ //输出函数a中的this对象 console.log(this); } //定义函数b function b(){} var obj = {name:'我是obj'}; //定义对象obj a.call(); //window a.call(null); //window a.call(undefined);//window a.call(1); //Number a.call(''); //String a.call(true); //Boolean a.call(b);// function b(){} a.call(obj); //Object
6.2 apply()
- 语法与
call()方法的语法几乎完全相同,唯一的区别在于,apply的第二个参数必须是一个包含多个参数的数组(或类数组对象)。
6.3 bind()
bind() 函数会创建一个新函数(称为绑定函数)
- bind是ES5新增的一个方法
- 传参和call类似
- 不会执行对应的函数,call或apply会自动执行对应的函数
- 返回对函数的引用
- 语法
fun.bind(thisArg[, arg1[, arg2[, ...]]])
6.4 练习
-
求数组中的最大和最小值
var arr = [34,5,3,6,54,6,-67,5,7,6,-8,687]; console.log(Math.max.apply(Math, arr)); console.log(Math.max.call(Math, 34,5,3,6,54,6,-67,5,7,6,-8,687)); console.log(Math.max.bind(Math, 34,5,3,6,54,6,-67,5,7,6,-8,687)()); console.log(Math.min.apply(Math, arr)); console.log(Math.min.call(Math, 34,5,3,6,54,6,-67,5,7,6,-8,687)); console.log(Math.min.bind(Math, 34,5,3,6,54,6,-67,5,7,6,-8,687)()); -
将伪数组转化为数组
var arrayLike = { 0: 'qianlong', 1: 'ziqi', 2: 'qianduan', length: 3 } console.log(Array.prototype.slice.call(arrayLike)); console.log([].slice.call(arrayLike));
6.5 面试题
function fn1() {
console.log(1);
}
function fn2() {
console.log(2);
}
fn1.call(fn2);
fn1.call.call(fn2);

浙公网安备 33010602011771号