this相关问题
1.apply、call、bind
- apply()和call()都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值
- apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组
- call()方法接收的第一个参数时在其中运行函数的作用域,剩余的都是传递给函数的参数
- 两者的真正作用是:扩充函数赖以运行的作用域
window.color = "red";
var o = {color: "blue"};
function sayColor(){
alert(this.color);
}
sayColor();
sayColor.call(this); // red
sayColor.call(o); //blue
- bind():创建一个函数的实例,其this值会被绑定到传给bind()函数的值
window.color = "red";
var o = {color: "blue"};
function sayColor(){
alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); // blue
sayColor()调用bind()并传入对象o,创建了objectSayColor()函数,objectSayColor()函数的this值等于o,因此即使是在全局作用域中调用这个函数,也会看到"blue"
2.以下代码输出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
输出: John: hi!
原因:sayHi()是作为john对象的方法调用的,因此this等于john对象.
3.下面代码输出什么,为什么
func()
function func() {
alert(this)
}
输出: window
原因: 当执行func()时,其实它是作为Window对象的方法调用的,因此,this指的是window
4.下面代码输出什么,为什么
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
输出:
document
window
原因: 事件处理函数中的this指的是其对应的dom对象,setTimeout中的this指的是window
5.下面代码输出什么,为什么
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
- 输出: John
- 原因: func.call()中传入了对象john,因此将func中this的值设置为了对象john
6.以下代码有什么问题,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}
-
问题:事件处理函数中的this指的是该事件处理函数绑定的对象,即$btn,因此该对象没有showMsg()方法
-
修改:在bind内部设置一个变量将this保存下来,这样在事件处理函数中使用该变量来调用showMsg方法
var module= {
bind: function(){
var _this = this;
$btn.on('click', function(){
console.log(this) //this指什么
_this.showMsg();
})
},
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("yanxin")
p.sayName();
2.上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。
原型链: 每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针.如果让原型对象等于另一个类型的实例,则原型对象将包含一个指向另一个原型的指针,相应的另一个原型也包含着一个指向另一个构造函数的指针.如此层层递进,就构成了实例与原型的链条,即原型链
3.对String做扩展,实现如下方式获取字符串中频率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
String.prototype.getMostOften = function(){
var hash = {};
var mostOften = '';
var count = 0;
for(var i = 0; i< this.length; i++){
if(!hash[this[i]]){
hash[this[i]] = 1;
}else {
hash[this[i]]++;
}
if(hash[this[i]] > count){
count = hash[this[i]];
mostOften = this[i];
}
}
return mostOften;
}
console.log(ch); //d , 因为d 出现了5次
4. instanceOf有什么作用?内部逻辑是如何实现的?
- 使用
object instanceof constructor
- 作用:检测 constructor.prototype 是否存在于参数 object 的原型链上
- 每个实例都包含一个指向原型对象的内部指针(proto),通过该指针可以找到其原型链上的所有内容,因此可以检测 constructor.prototype 是否存在于参数 object 的原型链上
继承相关:
1.继承有什么作用?
- 继承可以简化对事物的描述:子类可以继承父类的属性,因此只需定义子类特有的属性即可
- 通过继承可以提高代码的重用性:父类提供的方法,子类通过继承可以直接使用
2.下面两种写法有什么区别
//方法1
function People(name, sex){
this.name = name;
this.sex = sex;
this.printName = function(){
console.log(this.name);
}
}
var p1 = new People('yanxin', 2)
//方法2
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){
console.log(this.name);
}
var p1 = new Person('yanxin', 27);
- 方法1:将printName方法放在了构造函数中,但是由于使用了匿名函数,因此每个实例的printName方法都是不同的(尽管功能相同,但每个实例的printName方法都会占用内存空间),并没有实现代码的复用
- 方法2:将printName方法放在了Person的原型对象中,当Person的实例调用printName方法时,会沿着原型链,找到Person的原型对象,使用Person的原型对象中的printName方法,因此,尽管每个Person实例都可以调用printName方法,但是这些printName方法都指的是Person的原型对象中的printName方法.实现了代码的复用
3. Object.create 有什么作用?兼容性如何?
- Object.create的作用如下面的代码,即创建一个新的构造函数,然后将传入的对象作为这个构造函数的原型对象,最后返回一个由该构造函数创建的一个新实例.
function object(o){
function F() {};
F.prototype = o;
return new F();
}
- 由于Object.create()在ECMAScript5中新增的,因此在低版本浏览器中并不支持,例如IE 6,7,8
4.hasOwnProperty有什么作用? 如何使用?
-
hasOwnProperty这个方法可以用来检测一个对象是否含有特定的自身属性(和方法),该方法会忽略掉那些从原型链上继承到的属性(和方法)。
-
使用:
obj.hasOwnProperty(prop)
,prop指要检测的属性,可以是字符串或者Symbol,返回一个true或false。
5.如下代码中call的作用是什么?
function Person(name, sex){
this.name = name;
this.sex = sex;
}
function Male(name, sex, age){
Person.call(this, name, sex); //这里的 call 有什么作用
this.age = age;
}
- 通过call()方法,在(未来将要)新创建的Male实例的环境下调用了Person构造函数,这样就会在新Male对象上执行Person()函数中定义的所有对象初始化代码,Male的每个实例都会具有自己的name和sex属性.
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.call(this, name, sex);
this.age = age;
}
function inheritPrototype(subType, superType){
// 创建了一个只包含superType原型对象内容的对象
var prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
inheritPrototype(Male, Person);
Male.prototype.getAge = function(){
console.log(this.age);
};
var yanxin = new Male('闫鑫', '男', 22);
yanxin.getName();
网友评论