問(wèn)題1: apply、call 、bind有什么作用,什么區(qū)別.
var value = 100;
var obj4 = {
value: 200
}
function fn4(a, b) {
console.log(this.value + a + b);
}
fn4(3,4); // 107
fn4.call(obj4, 3, 4) // 207
var f = fn4.bind(obj4); // this指代obj4里的this
f(3,4); // 207
fn4.apply(obj4, [3,4]) // 207
Function.prototype.bind
bind,返回一個(gè)新函數(shù),并且使函數(shù)內(nèi)部的this為傳入的第一個(gè)參數(shù)。
使用call和apply設(shè)置this
fn.call(obj, param1,param2)
fn.apply(obj, paramArray);
第一個(gè)參數(shù)都是希望設(shè)置的this對(duì)象,不同之處在于call方法接受參數(shù)列表,而apply接受參數(shù)數(shù)組。
問(wèn)題2: 以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
輸出 John: hi!
相當(dāng)于
var john = {
firstName: "John"
sayHi: function() {
alert(this.firstName + ": hi!")
}
}
john.sayHi() // 這里是john對(duì)象調(diào)用,那么this指代john對(duì)象
問(wèn)題3: 下面代碼輸出什么,為什么
func()
function func() {
alert(this)
}
輸出 window
在函數(shù)被直接調(diào)用時(shí)this綁定到全局對(duì)象。在瀏覽器中,window就是該全局對(duì)象
問(wèn)題4:下面代碼輸出什么
document.addEventListener('click', function(e){
console.log(this); // #document // 指代綁定事件的對(duì)象即document
setTimeout(function(){
console.log(this); // window // 定時(shí)器里執(zhí)行函數(shù)中的this指代全局對(duì)象
}, 200);
}, false);
問(wèn)題5:下面代碼輸出什么,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john) // John
因?yàn)檎{(diào)用call方法,那么this指代的就是傳入的對(duì)象。
問(wèn)題6: 以下代碼有什么問(wèn)題,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
問(wèn)題 this指代的是$btn 而不是module了,因此調(diào)用showMsg方法,這樣是錯(cuò)誤的.
修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
}.bind(this))
},
showMsg: function(){
console.log('饑人谷');
}
}
原型鏈相關(guān)問(wèn)題
問(wè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();
當(dāng)new一個(gè)函數(shù)的時(shí)候,首先會(huì)創(chuàng)建一個(gè)新對(duì)象p,其次會(huì)
執(zhí)行這個(gè)函數(shù),同時(shí),函數(shù)里面的this就會(huì)指向這個(gè)新創(chuàng)建的對(duì)象,如果
對(duì)this進(jìn)行賦值或者進(jìn)行操作那么就是對(duì)這個(gè)對(duì)象進(jìn)行賦值,操作。
當(dāng)函數(shù)執(zhí)行完之后,會(huì)把剛剛創(chuàng)建的對(duì)象給return出來(lái)。
把對(duì)象的proto指向了函數(shù)的prototype屬性。
p1.proto.constructor === Person
Person.prototype.constructor === Person
p1.constructor === Person; // 它自己沒(méi)有就會(huì)去原型里面找
問(wèn)題8: 上例中,對(duì)對(duì)象 p可以這樣調(diào)用 p.toString()。toString是哪里來(lái)的? 畫出原型圖?并解釋什么是原型鏈。


因?yàn)槿魏晤惖膒rototype屬性本質(zhì)上都是個(gè)類Object的實(shí)列,所以prototype也和其他實(shí)列一樣也有個(gè)proto內(nèi)部屬性,指向其類型Object的prototype。自己類型的prototype找不到的話,還會(huì)找prototype的類型的prototype屬性。
下面再看這個(gè)列子,如圖
p1下面沒(méi)有toString(),那么向它的原型上找,即p1.proto ==== Person.prototype.
我們發(fā)現(xiàn)Person下也沒(méi)有toString().再向它的原型上找 即Person.prototype.proto === Object.prototype
這個(gè)時(shí)候我們發(fā)現(xiàn)Object的prototype屬性里有toString().
這就是原型鏈,如果還有找到的話,那么就返回undefined。
問(wèn)題9:對(duì)String做擴(kuò)展,實(shí)現(xiàn)如下方式獲取字符串中頻率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因?yàn)閐 出現(xiàn)了5次
// 針對(duì)全是小寫字母的情況
String.prototype.getMostOften = function() {
var arr = [];
var letterCount = 'z'.charCodeAt() - 'a'.charCodeAt();
for(var i = 0; i < letterCount; i++) {
arr[i] = 0;
}
for(var i = 0; i < this.length; i++) {
arr[this[i].charCodeAt()-'a'.charCodeAt()]++;
}
return Math.max.apply(null, arr);
}
var ch = str.getMostOften();
console.log(ch); // 5
問(wèn)題10: instanceOf有什么作用??jī)?nèi)部邏輯是如何實(shí)現(xiàn)的?
判斷一個(gè)對(duì)象是不是某個(gè)類型的實(shí)列。
舉列說(shuō)明
[1,2,3] instanceof Array
[1,2,3] instanceof Object
[1,2,3].__proto__ === Array.prototype // ture
[1,2,3].__proto__.___proto__ === Object.prototype // true
a instanceof b
只要判斷a的原型是否等于b的prototype屬性。如果不相等,繼續(xù)判斷a的原型的原型是否等于
b的prototype屬性,如果不相等,那么就繼續(xù)找,直到,找到最后,沒(méi)有找到能相等的,那么就返回false
繼承相關(guān)問(wèn)題
問(wèn)題11:繼承有什么作用?
1、得到一個(gè)類的屬性
2、得到一個(gè)類的方法
問(wèn)題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);
方法1每次創(chuàng)建一個(gè)對(duì)像都會(huì)創(chuàng)建printName函數(shù)。而printName方法實(shí)際上作用的相同的,會(huì)浪費(fèi)大量的內(nèi)存
方法2 printName函數(shù)是共用的,這樣避免了重復(fù)
問(wèn)題13: Object.create 有什么作用?兼容性如何?
舉列說(shuō)明
var b = {};
a = Object.create(b);
a.__proto__ === b; // true; 即a的原型為b
es5

問(wèn)題14: hasOwnProperty有什么作用? 如何使用?
hasOwnPersonty是Object.prototype的一個(gè)方法,可以判斷一個(gè)對(duì)象是否包含自定義屬性而不是
原型鏈上的。
舉列說(shuō)明
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
sayName: function() {
console.log("My name is " + this.name);
},
walk: function() {
console.log(this.name + ' is walking');
}
}
var p1 = new Person('tangyue', '20');
p1.hasOwnProperty('name') // ture
p1.hasOwnProperty('sayName') // false
問(wèn)題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;
}
作用: 將Person方法內(nèi)部的this指向Male創(chuàng)建的實(shí)列對(duì)象。
問(wèn)題16: 補(bǔ)全代碼,實(shí)現(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);
}
Male.prototype = Object.create(Person.prototype);
Male.prototype.getAge = function(){
console.log(this.age);
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.getName(); // 若愚