this相關(guān)問題
問題1:apply洋访、call有什么作用读串,什么區(qū)別
-
apply()
和call()
函數(shù)都可以 指定this值和參數(shù)值的情況下調(diào)用某個函數(shù)。 -
call()
和apply()
的作用一樣,區(qū)別在于提供給原函數(shù)的參數(shù)的方式不一樣 -
apply()
函數(shù)只接受兩個參數(shù),提供給原函數(shù)的參數(shù)以數(shù)組或類數(shù)組對象的形式存在
-
- 而
call()
接收無限個參數(shù)廓旬, 第二個參數(shù)及其后面的參數(shù)就是提供給原函數(shù)的參數(shù)。
- 而
問題2:以下代碼輸出什么
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi() // 彈出John:hi谐腰!
問題3: 下面代碼輸出什么孕豹,為什么
func() // 彈出window對象
function func() {
alert(this)
}
- 因為在函數(shù)
func()
被直接調(diào)用時,this綁定到全局對象十气。在瀏覽器中励背,window 就是該全局對象
問題4:下面代碼輸出什么
function fn0(){
function fn(){
console.log(this);
}
fn();
}
fn0(); // 輸出window對象
document.addEventListener('click', function(e){
console.log(this); // 輸出document對象
setTimeout(function(){
console.log(this); // 輸出window對象
}, 200);
}, false);
問題5:下面代碼輸出什么,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john) // 彈出John
-
func()
函數(shù)通過call()
函數(shù)調(diào)用砸西,此時this為John對象叶眉,john.firstName存在,輸出"John"
問題6: 以下代碼有什么問題籍胯,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) // 這里的this指的是$btn
this.showMsg(); // $btn沒有showMsg的屬性竟闪,如果調(diào)用,這里會報錯
})
},
showMsg: function(){
console.log('饑人谷');
}
}
- 應(yīng)該改成如下:
var module= {
bind: function(){
var self = this; // 先在外部將this保存成變量杖狼,再在內(nèi)部調(diào)用這個變量
$btn.on('click', function(){
console.log(this);
self.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
這樣,再進行測試妖爷,發(fā)現(xiàn)成功輸出饑人谷
原型鏈相關(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();
-
People
是一個構(gòu)建函數(shù)熄攘,protoType
是People
的屬性(原型),即可以通過People.protoType
的方式來獲取這個屬性彼念,其類型是一個對象挪圾。 -
p
是People
構(gòu)建的實例浅萧,它有一個屬性__proto__
,它的值引用了p
的父類People
的protoType
屬性哲思。 -
constructor
是protoType
的一個屬性洼畅,其值指向函數(shù)本身,例如:People.protoType.constructor
就是People
本身棚赔。
問題8: 上例中帝簇,對對象 p可以這樣調(diào)用 p.toString()。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈靠益。
- toString()實際上是Object的方法
- 如上原型圖所示:對對象p調(diào)用
p.toString()
時丧肴,JS先從其自身的方法中找toString()
方法,沒有找到胧后;
- 如上原型圖所示:對對象p調(diào)用
- 然后通過
__proto__
屬性找其父元素People
的protoType
屬性中有沒有toString()
方法芋浮,依然沒找到;
- 然后通過
- 然后再通過其父元素
People
的protoType
屬性中的__proto__
屬性即Object.protoType
繼續(xù)尋找绩卤,在Object.protoType
找到了toString()
方法途样。
- 然后再通過其父元素
- 每個對象都有一個隱藏的
__proto__
屬性,這個屬性就是對其父元素原型對象(protoType
)的引用濒憋。 - 由于原型對象本身也是對象何暇,也有
__proto__
屬性,它的__proto__
屬性又指向了其更高父元素原型對象凛驮。這樣就形成了一條鏈裆站,這就是原型鏈。
問題9:對String做擴展黔夭,實現(xiàn)如下方式獲取字符串中頻率最高的字符
// 答案
String.prototype.getMostOften = function(){
var box = {},
max = 0,
maxKey = "";
for (var i=0, word;i<this.length;i++) {
word = this[i];
if (box[word] === undefined) {
box[word] = 1;
} else {
box[word] += 1;
}
}
for (key in box) {
if (box[key] > max) {
max = box[key];
maxKey = key;
}
}
return maxKey
}
// 題目
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現(xiàn)了5次
問題10: instanceOf有什么作用宏胯?內(nèi)部邏輯是如何實現(xiàn)的?
-
instanceof
用來檢查一個對象是不是另一個構(gòu)造對象的實例本姥。 - 其內(nèi)部邏輯是測試一個對象在其原型鏈中是否存在一個構(gòu)造函數(shù)的 prototype 屬性肩袍。
- 所以如果表達式
obj instanceof Foo
返回true
,則并不意味著該表達式會永遠返回true
婚惫,因為Foo.prototype
屬性的值有可能會改變氛赐,改變之后的值很有可能不存在于obj
的原型鏈上,這時原表達式的值就會成為false
先舷。
繼承相關(guān)問題
問題11:繼承有什么作用?
- 繼承的主要作用有兩個
- 繼承可以使子類共享父類的屬性和方法
- 繼承可以覆蓋和擴展父類的屬性和方法
問題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);
- 第一種方法將會把
printName
這個方法重新定義在每個構(gòu)建的對象上艰管,這樣如果構(gòu)建的對象比較多,也將會有許多個printName
函數(shù)蒋川,將會對性能產(chǎn)生影響 - 第二種方法會把
printName
這個方法定義到構(gòu)建函數(shù)的protoType
上牲芋,這樣新構(gòu)建的函數(shù)將會通過原型鏈獲取到這個方法,節(jié)約了內(nèi)存 - 推薦使用第二種方法
問題13: Object.create 有什么作用?兼容性如何缸浦?
-
Object.create
方法可以創(chuàng)建一個擁有指定原型和若干個指定屬性的對象夕冲。 - 在繼承中,
Object.create
可以用于繼承屬性餐济。 -
Object.create
是在ES5中規(guī)定的耘擂,其兼容性見下圖:
問題14: hasOwnProperty有什么作用? 如何使用絮姆?
-
hasOwnProperty
方法會返回一個布爾值醉冤,其用來判斷某個對象是否含有特定的自身屬性,該方法會忽略掉那些從原型鏈上繼承到的屬性篙悯。 - 語法為
obj.hasOwnProperty(prop)
蚁阳,參數(shù)prop
為要檢測的屬性
問題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
的作用是改變構(gòu)造函數(shù)People
的作用域,這樣就可以讓People
在Male
的作用域中執(zhí)行鸽照,這樣People
中的一些屬性賦值語句也會在Male
中執(zhí)行螺捐。 - 通過這種方式就實現(xiàn)了屬性的繼承。
問題16: 補全代碼矮燎,實現(xiàn)繼承
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;
}
var _prototype = Object.create(Person.prototype);
_prototype.consturctor = Male;
Male.prototype = _prototype;
Male.prototype.getAge = function(){
console.log(this.age);
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.getName();