Part1:this
1.apply、call 有什么作用,什么區別
apply和call的作用是給function函數去指定this和參數;
apply語法:func.apply(thisValue, [arg1, arg2, ...]);
call語法:func.call(thisValue, arg1, arg2, ...)
this.value
在func運行時指定的this值。需要注意的是,指定的 this 值并不一定是該函數執行時真正的 this 值
,如果這個函數處于非嚴格模式下,則指定為 null 或 undefined 時會自動指向全局對象(瀏覽器中就是window對象),
同時值為原始值(數字,字符串,布爾值)的 this 會指向該原始值的自動包裝對象。
apply和call的區別:
apply函數的語法與call的語法幾乎完全相同,唯一的區別在于,call方法接受的是一個參數列表,而apply方法接受的是一個包含多個參數的數組(或類數組對象)
2. 以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
//輸出John: hi!
this指向對象john
3.下面代碼輸出什么,為什么
func()
function func() {
alert(this)
}
輸出為[Object window],.//因為func函數在全局對象中運行
4.下面代碼輸出什么
document.addEventListener('click', function(e){
console.log(this);//document,在事件處理程序中,this代表事件源的DOM對象
setTimeout(function(){
console.log(this);//window ,setTimeout和setInterval這兩個方法執行
的函數指向全局對象
}, 200);
}, false);
5.下面代碼輸出什么,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
輸出:Jhon,因為使用call這個方法將func的this綁定在john這個對象上
6.以下代碼有什么問題,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指$btn這個DOM對象,因此此時的this不在指向module,所有找不到
showMsg這個方法
this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
-----------------------------------------------------
修改:
var module= {
bind: function(){
var _this = this;
$btn.on('click', function(){
console.log(this) //$btn
_this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
Part2:原型鏈
7.有如下代碼,解釋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("若愚")
p.sayName();
Person是一個構造函數,也是一個 對象,這個對象里存在一個prototype屬性,而構造函數內部定義了一些屬性和方法,這些屬性和方法是屬于該類的所有實例的特征;
prototype是一個構造函數的原型對象,其擁有constructor和proto屬性,而constructor這個屬性是指向構造函數Person,而proto指向該對象的原型;
p是通過構造函數Person構造出來的實例,也是擁有proto屬性。所以p.proto === Person.prototype;
8.上例中,對對象 p可以這樣調用 p.toString()。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈。
p調用toString()時,首先會從自己查看toString()這個方法,如果沒有則會沿著proto這個屬性進入Person的prototype里面查看,如果還是沒有找到toString()這個方法,會沿著prototype.proto的屬性去到Object的prototype里查看,最后找到toString(),然后調用。
原型鏈:由于原型對象本身也是對象,而每個javascript對象都有一個原型對象,每個對象都有一個隱藏的proto屬性,原型對象也有自己的原型,而它自己的原型對象又可以有自己的原型,這樣就組成了一條鏈,這個就是原型鏈。在訪問對象的屬性時,如果在對象本身中沒有找到,則會去原型鏈中查找,如果找到,直接返回值,如果整個鏈都遍歷且沒有找到屬性,則返回undefined。原型鏈一般實現為一個鏈表,這樣就可以按照一定的順序來查找。
9.對String做擴展,實現如下方式獲取字符串中頻率最高的字符
String.prototype.getMostOften = function(){
var obj = {},
most = 0,
which;
for(var i=0 ,str; i<this.length;i++){
str = this[i];
if(obj[str]){
obj[str] += 1;
}else{
obj[str] = 1;
}
}
for(var key in obj){
if(obj[key] > most){
most = obj[key];
which = key;
}
}
return which;
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現了5次
10. instanceOf有什么作用?內部邏輯是如何實現的?
instanceOf的作用是用來判斷對象是否是另一個的對象的實例,并返回布爾值。
Object.prototype.instaceOf = function(obj1,obj2){
var obj1 = obj1.__proto__;
while(obj1.__proto__){
if(obj1 === obj2.prototype){
return true;
}else{
obj1 = obj1.__proto__;
}
return false;
}
11.繼承有什么作用?
- 可以使子類共享父類的屬性和方法;
- 可以覆蓋和擴展父類的屬性和方法。
12.下面兩種寫法有什么區別?
//方法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方法定義在構造函數People內,如果構建的對象比較多,代碼就會很多,對性能造成負面影響;
方法二將printNmae方法定義在Person的原型對象內,這樣構建出來的對象,即使內部沒有定義,還是能夠通過原型鏈得到此方法,節約了內存。這種方法比較先進。
13.Object.create 有什么作用?兼容性如何?
Object.create() 方法創建一個擁有指定原型和若干個指定屬性的對象。Object.create是在ES5中規定的,IE9以下無效。
14 hasOwnProperty有什么作用? 如何使用?
hasOwnPerperty
是Object.prototype
的一個方法,可以判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性,hasOwnProperty
是JavaScript中唯一一個處理屬性但是不查找原型鏈的函數。
用法
obj.hasOwnPerperty('key') // true or false;
ex:
Person.hasOwnPerperty('name')//true;
15.如下代碼中call的作用是什么?
function Person(name, sex){
this.name = name;
this.sex = sex;
}
function Male(name, sex, age){
Person.call(this, name, sex); ////調用Person函數,使Male函數能夠執行Person上的初始化代碼,實現構造函數繼承,
并且使Person執行時的this指向Male;
this.age = age;
}
16.補全代碼,實現繼承
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){
console.log(this.name);
};
function Male(name, sex, age){
Person.apply(this,[name,sex]);
this.age = age;
}
Male.prototype = Object.create(Person.prototype) ;
Male.prototype.constructor = Male;
Male.prototype.getAge = function(){
console.log(this.age);
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
感謝瓜子觀眾!!!-。-
