this 相關(guān)問題
問題1: apply、call 有什么作用,什么區(qū)別
-
區(qū)別:
apply():在使用一個指定this值和參數(shù)(參數(shù)以數(shù)組或類數(shù)組對象的形式存在)的情況下調(diào)用某個函數(shù)的方法。fun.apply(thisArg[, argsArray])(只接受兩個參數(shù))call():在使用一個指定的this值和若干個指定的參數(shù)值的前提下調(diào)用某個函數(shù)或方法。fun.call(thisArg[, arg1[, arg2[, ...]]])(接受的參數(shù)個數(shù)沒有上限)
-
作用:
能夠指定函數(shù)的
this如下例:window.color = 'red'; var o = {color:'blue'}; var o2 = {color:'yellow'}; function sayColor() { console.log(this.color); } sayColor(); //"red" sayColor.call(this); //"red" sayColor.call(window); //"red" 上面三個this都是全局對象window sayColor.call(o); //"blue" 這里通過call把this指向了o sayColor.apply(o2); //"yellow" 這里通過apply吧this指向了o2
進而衍生出我們可以使用call來得到一個類的屬性從而實現(xiàn)繼承。
?
問題2: 以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
彈出"John:hi!"
問題3: 下面代碼輸出什么,為什么
func()
function func() {
alert(this)
}
彈出window對象。 原因:因為在函數(shù)func()被直接調(diào)用時,this綁定到全局對象。在瀏覽器中,window 就是該全局對象。
問題4:下面代碼輸出什么
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
分別是:#document 、 window
原因:1. 我們可以看出document綁定click事件所以此時的this是指document 2.setTimeout、setInterval這兩個方法執(zhí)行的函數(shù)this也是全局對象
問題5:下面代碼輸出什么,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
彈出:"John"
call()能夠指定函數(shù)的this 。此時func.call(john)所以this也就是john。
問題6: 以下代碼有什么問題,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
代碼中注釋處的this是指#btn。而#btn是沒有showMsg()方法的 。
修改:
var module= {
bind: function(){
var _this = this; //此處的this是指module,通過賦值給 _this 可以在下面調(diào)用。
$btn.on('click', function(){
_this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
原型鏈相關(guān)問題
問題7:有如下代碼,解釋Person、 prototype、__proto__、p、constructor之間的關(guān)聯(lián)。
function Person(name){
this.name = name;
}
Person.prototype.sayName = function(){
console.log('My name is :' + this.name);
}
var p = new Person("若愚")
p.sayName();
Preson是構(gòu)造函數(shù),也是一個對象。
p為Person的實例,擁有Person原型鏈上的屬性和方法
p.__proto__指向Person.prototype
Person.prototype.constructor指向Person
問題8: 上例中,對對象 p可以這樣調(diào)用 p.toString()。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈。

可以從原型圖中看出toString是Object.prototype的方法,p先通過p.__proto__ 找Person.prototype中的方法,然而沒找到。然后接著p.__proto__.__proto__就找到了。
原型鏈:由于原型對象本身也是對象,而每個javascript對象都有一個原型對象,每個對象都有一個隱藏的__proto__屬性,原型對象也有自己的原型,而它自己的原型對象又可以有自己的原型,這樣就組成了一條鏈,這個就是原型鏈。在訪問對象的屬性時,如果在對象本身中沒有找到,則會去原型鏈中查找,如果找到,直接返回值,如果整個鏈都遍歷且沒有找到屬性,則返回undefined。原型鏈一般實現(xiàn)為一個鏈表,這樣就可以按照一定的順序來查找。
問題9:對String做擴展,實現(xiàn)如下方式獲取字符串中頻率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現(xiàn)了5次
String.prototype.getMostOften = function(){
var obj = {};
for(var i=0;i<this.length;i++){
var n = this[i];
if(obj[n]){
obj[n]++
}else{
obj[n] = 1
}
}
var max = 0,
key;
for(var n in obj){
if(obj[n]>max){
max = obj[n];
key = n;
}
}
return key;
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch);
問題10: instanceOf有什么作用?內(nèi)部邏輯是如何實現(xiàn)的?
instanceof 是一個運算符。A instanceof B用于判斷A 是否是B 的一個實例,或者是A是否是以B為父類型的一個實例。
內(nèi)部邏輯:instanceOf相當于如下函數(shù)isInstanceof
function isInstanceOf(obj, fn){
var oldProto = obj.__proto__;
do{
if(oldProto === fn.prototype){
return true;
}else{
oldProto = oldProto.__proto__;
console.log(oldProto);
}
}while(oldProto)
return false;
}
繼承相關(guān)問題
問題11:繼承有什么作用?
繼承可以使一個對象直接使用另一個對象的方法和屬性??梢灾貙懞蛿U展父類的屬性和代碼,又不影響父類本身。
問題12: 下面兩種寫法有什么區(qū)別?
//方法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);


從上兩圖可以看出:方法一的寫法是屬性方法都寫入p1中;方法二中的p1只有屬性name和sex,方法綁定在Person.prototype屬性下,p1可以繼承父類的屬性和方法。這樣做的好處是節(jié)約代碼量,提高性能。
問題13: Object.create 有什么作用?兼容性如何?
Object.create()創(chuàng)建一個具有指定原型且可選擇性地包含指定屬性的對象。可以通過Object.create()方法實現(xiàn)類式繼承,如:
Male.prototype = Object.create(Person.prototype);
通過Object.create() clone了一個新的prototype,使Male.prototype指向這個新的prototype,而不是直接將Person.prototype賦值給它,這樣做可以避免當修改Male.prototype的時候不會將它的父類Person.prototype也修改了。
兼容性:

問題14: hasOwnProperty有什么作用? 如何使用?
作用:hasOwnPerperty是Object.prototype的一個方法,可以判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性,hasOwnProperty是JavaScript中唯一一個處理屬性但是不查找原型鏈的函數(shù)。
使用:m.hasOwnProperty('name');
m.hasOwnProperty('printName');
Male.prototype.hasOwnProperty('printAge');
問題15:如下代碼中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可以指定函數(shù)的this ,所以這里的call指定Person中的this為Male。從而讓函數(shù)Male可以調(diào)用Person的屬性。
問題16: 補全代碼,實現(xiàn)繼承
function Person(name, sex){
this.name = name;
this.sex = sex;
this.printName = function(){
console.log(name)
}
}
Person.prototype.getName = function(){
console.log(this.name)
};
function Male(name, sex, age){
Person.call(this, name, sex);
this.age = age;
}
Male.prototype = Object.create(Person.prototype)
Male.prototype.getAge = function(){
console.log(this.age)
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
ruoyu.getAge();
ruoyu.getName();
