一. this
参考
1.深入浅出妙用 Javascript 中 apply、call、bind
2.理解 JavaScript 中的 Function.prototype.bind
3.this 关键字
1. apply、call 、bind有什么作用,什么区别
- 作用:三者都可以固定this的值,避免出现意想不到的情况
- fun.call(thisArg[, arg1[, arg2[, ...]]])
call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表) - fun.apply(thisArg, [argsArray])
apply方法的作用与call方法类似,也是改变this指向,然后再调用该函数。唯一的区别就是,它接收一个数组或类数组对象作为函数执行时的参数 - fun.bind(thisArg[, arg1[, arg2[, ...]]])
创建了一个函数,当这个函数在被调用的时候,它的 this 会被设置成被传入第一个值。
- fun.call(thisArg[, arg1[, arg2[, ...]]])
- 区别:
1.apply
/call
与bind
bind改变了this值后没有立即执行,而apply和call都是立即执行的
var obj = {
a:1
}
var foo = {
getA: function(){
console.log(this.a)
}
}
foo.getA() //undefined
foo.getA.bind(obj)() //1
foo.getA.call(obj) //1
foo.getA.apply(obj) //1
2.apply
和call
apply的第二个参数是数组或类数组对象,call接受的则是若干个参数
var arr = [1,2,3,4,9]
console.log(Math.max.apply(Math,arr)) //9
console.log(Math.max.call(Math,1,2,3,4,9))//9
2.以下代码输出?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func //john对象添加sayHi方法,方法为func
john.sayHi() //"John: hi!" 执行,此时this为john
3.以下代码输出?
func() //[object Window] 全局作用域下函数,this绑定为全局对象
function func() {
alert(this)
}
4.以下代码输出?
document.addEventListener('click', function(e){
console.log(this); //document 在事件处理程序中this代表事件源对象
setTimeout(function(){
console.log(this); //window setTimeout函数始终是在全局作用域下调用的,所以this在非严格模式下指向window
}, 200);
}, false);
5.以下代码输出?
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
//John call方法将func的this指定为john对象,所以this.firstName就是"John"了
6.以下代码有什么问题,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么$btn而并非module,不能调用module下的showMsg方法
this.showMsg();
})
},
showMsg: function(){
console.log('没什么');
}
}
//修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this)
this.showMsg();
}.bind(this))
},
showMsg: function(){
console.log('没什么');
}
}
二.原型链
1.有如下代码,解释Person、 prototype、proto、p、constructor之间的关联。
function Person(name){
this.name = name;
}
Person.prototype.sayName = function(){
console.log('My name is :' + this.name);
}
var p = new Person("haha")
p.sayName();
//1.定义Person构造函数,Person构造函数自带prototype属性
//2.prototype属性中有constructor属性,指向构造函数
//3.每个构造函数的实例都有__proto__属性,指向构造函数的prototype属性
2.上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。
如图示,Person构造函数中没有toString()方法,所以继续在其原型中查找,也没有,所以Person.prototype的原型,即Object.prototype中查找,然后找到了对象原型中的toString()方法
对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)原文链接
3.对String做扩展,实现如下方式获取字符串中频率最高的字符
String.prototype.getMostOften = function(){
var i, obj = {}
var textSplit = this.split('')
for(i= 0; i index){
max = key
index = obj[key]
}
}
return max
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
4.instanceof有什么作用?内部逻辑是如何实现的?
- instanceof判断对象是否为某个构造函数的实例;
- 内部逻辑:判断构造函数的原型是否在对象的原型链上,在就返回true,反之false
//例
function Person(name){
this.name = name;
}
Person.prototype.sayName = function(){
console.log('My name is :' + this.name);
}
var p = new Person("haha")
console.log(p instanceof Person) //true
console.log(p instanceof Object) //true
三.继承
1.继承有什么作用?
继承是指一个对象可以直接使用另一个对象的属性和方法,继承提高了代码复用性,减少重复劳动
2.下面两种写法有什么区别?
方法1的实例之间属性和方法都是独立的,共用的属性和方法不能共享,同时也浪费资源
方法2的实例之间printName方法是共享的
//方法1
function People(name, sex){
this.name = name;
this.sex = sex;
this.printName = function(){
console.log(this.name);
}
}
var p1 = new People('饥人谷', 2)
//方法2
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){
console.log(this.name);
}
var p1 = new Person('若愚', 27);
3.Object.create 有什么作用?兼容性如何?
Object.create(proto, [ propertiesObject ])
:创建一个对象,使其原型为传入的第一个参数
兼容性:IE 9+
4.hasOwnProperty有什么作用? 如何使用?
hasOwnPerperty
是Object.prototype
的一个方法,可以判断一个对象是否包含自定义属性而不是原型链上的属性,hasOwnProperty
是JavaScript中唯一一个处理属性但是不查找原型链的函数
function Person(name, sex){
this.name = name
this.sex = sex
this.printSex = function(){
console.log(this.sex)
}
}
Person.prototype.printName = function(){
console.log(this.name);
}
var p1 = new Person('小明', 27);
console.log(p1.hasOwnProperty('printSex')) //true
console.log(p1.hasOwnProperty('printName')) //false
5.如下代码中call的作用是什么?
function Person(name, sex){
this.name = name;
this.sex = sex;
}
function Male(name, sex, age){
Person.call(this, name, sex); //这里的call 用于继承Person的属性
this.age = age;
}
//在实例化后male里面就可以获取到name,sex属性
var male1 = new Male('xiaoming','男',12)
console.log(male1.name,male1.sex,male1.age) //xiaoming 男 12
6.补全代码,实现继承
function Person(name, sex){
this.name = name
this.sex = sex
}
Person.prototype.getName = function(){
console.log(this.name)
};
function Male(name, sex, age){
Person.bind(this)(name,sex)
this.age = age
}
var _prototype = Object.create(Person.prototype)
_prototype.constructor = Male
Male.prototype = _prototype
Male.prototype.getAge = function(){
console.log(this.age)
};
var ruoyu = new Male('ruoyu', '男', 27);
ruoyu.getName();//ruoyu