一丶call方法
call方法有两个作用:调用函数以及改变函数中的this
-
调用函数语法:
函数.call()
-
call方法在调用函数的同时传递参数就可以改变this的含义
语法:
函数.call(新的this含义)
function fn() { console.log(this) } fn() // window fn.call(document) // document
函数.call(新的this含义, 实参1, 实参2, ...)
function fn(a, b) { var c = a + b console.log(c) console.log(this) } fn(1, 2) // 3 window fn.call(document, 2, 3) // document 5 fn.call(null, 5, 6) // window 11 修改this的含义为null,this指向window
二丶apply方法
apply方法跟call方法相同,主要是传递实参方式不同,apply传参需要是一个参数数组
语法:
函数.call(新的this含义, [实参1, 实参2, ...])
function fn(a, b) {
var c = a + b
console.log(c)
console.log(this)
}
fn(1, 2) // 3 window
fn.apply(document, [2, 3]) // document 5
三丶bind方法
bind方法主要有两个作用:复制函数,改变新函数中this的含义
复制函数
语法:
函数.bind() // 返回新函数
function fn() {
console.log(this)
}
var newFn = fn.bind()
console.log(newFn)
console.log(fn)
console.log(newFn === fn) // false
复制出来的新函数和原来的函数一模一样,但不是同一个
改变新函数的this
语法:
函数.bind(新的this含义) // 返回的新函数中,this的含义会变成新的含义
例:
function fn() {
console.log(this)
}
var newFn = fn.bind(document)
fn() // window
newFn() // document
bind不加参数,新函数的this为window:
var obj = {
name: '张三',
eat: function() {
console.log(this);
}
}
var fn = obj.eat.bind()
fn() // window
四丶call,apply,bind的区别
1丶相同点
- 三个都是用于改变this指向;
- 接收的第一个参数都是this要指向的对象;
- 都可以利用后续参数传参
2丶不同点
- call和bind传参相同,多个参数依次传入;
- apply只有两个参数,第二个参数为数组;
- call和apply都是对函数进行直接调用,而bind方法不会立即调用函数,而是返回一个修改this后的函数;
五丶继承方式
-
原型继承
通过修改对象的原型,将子对象的原型变为父对象的原型。
缺点:
1.来自原型对象的所有属性被所有实例共享
2.创建子类实例时,无法向父类构造函数传参
-
借用函数继承
在子构造函数中通过call调用父构造函数并改变其中的this为子构造函数的this
缺点:
1.只能继承父类在构造函数里声明的属性和方法,不能继承父级原型链上的属性和方法
2.影响性能
-
组合继承
原型继承+借用函数继承
缺点:
调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了),影响性能
-
ES6–class继承
跟组合继承的效果是一样的。
如果子类中有constructor方法的话,必须在constructor中的第一行代码调用
super()
方法,否则会报错。 (比较完美的继承)