問題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驶沼,返回一個新函數(shù),并且使函數(shù)內(nèi)部的this為傳入的第一個參數(shù)争群。
使用call和apply設置this
fn.call(obj, param1,param2)
fn.apply(obj, paramArray);
第一個參數(shù)都是希望設置的this對象回怜,不同之處在于call方法接受參數(shù)列表,而apply接受參數(shù)數(shù)組。
問題2: 以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
輸出 John: hi!
相當于
var john = {
firstName: "John"
sayHi: function() {
alert(this.firstName + ": hi!")
}
}
john.sayHi() // 這里是john對象調(diào)用,那么this指代john對象
問題3: 下面代碼輸出什么玉雾,為什么
func()
function func() {
alert(this)
}
輸出 window
在函數(shù)被直接調(diào)用時this綁定到全局對象翔试。在瀏覽器中,window就是該全局對象
問題4:下面代碼輸出什么
document.addEventListener('click', function(e){
console.log(this); // #document // 指代綁定事件的對象即document
setTimeout(function(){
console.log(this); // window // 定時器里執(zhí)行函數(shù)中的this指代全局對象
}, 200);
}, false);
問題5:下面代碼輸出什么复旬,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john) // John
因為調(diào)用call方法,那么this指代的就是傳入的對象垦缅。
問題6: 以下代碼有什么問題,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
問題 this指代的是$btn 而不是module了驹碍,因此調(diào)用showMsg方法壁涎,這樣是錯誤的.
修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
}.bind(this))
},
showMsg: function(){
console.log('饑人谷');
}
}
原型鏈相關問題
問題7:有如下代碼,解釋Person志秃、 prototype怔球、proto、p浮还、constructor之間的關聯(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();
當new一個函數(shù)的時候,首先會創(chuàng)建一個新對象p钧舌,其次會
執(zhí)行這個函數(shù)担汤,同時,函數(shù)里面的this就會指向這個新創(chuàng)建的對象延刘,如果
對this進行賦值或者進行操作那么就是對這個對象進行賦值漫试,操作六敬。
當函數(shù)執(zhí)行完之后碘赖,會把剛剛創(chuàng)建的對象給return出來。
把對象的proto指向了函數(shù)的prototype屬性外构。
p1.proto.constructor === Person
Person.prototype.constructor === Person
p1.constructor === Person; // 它自己沒有就會去原型里面找
問題8: 上例中普泡,對對象 p可以這樣調(diào)用 p.toString()。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈审编。
因為任何類的prototype屬性本質(zhì)上都是個類Object的實列撼班,所以prototype也和其他實列一樣也有個proto內(nèi)部屬性,指向其類型Object的prototype垒酬。自己類型的prototype找不到的話砰嘁,還會找prototype的類型的prototype屬性。
下面再看這個列子,如圖
p1下面沒有toString()勘究,那么向它的原型上找矮湘,即p1.proto ==== Person.prototype.
我們發(fā)現(xiàn)Person下也沒有toString().再向它的原型上找 即Person.prototype.proto === Object.prototype
這個時候我們發(fā)現(xiàn)Object的prototype屬性里有toString().
這就是原型鏈,如果還有找到的話口糕,那么就返回undefined缅阳。
問題9:對String做擴展,實現(xiàn)如下方式獲取字符串中頻率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現(xiàn)了5次
// 針對全是小寫字母的情況
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
問題10: instanceOf有什么作用景描?內(nèi)部邏輯是如何實現(xiàn)的十办?
判斷一個對象是不是某個類型的實列秀撇。
舉列說明
[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ù)找件相,直到虏等,找到最后,沒有找到能相等的适肠,那么就返回false
繼承相關問題
問題11:繼承有什么作用?
1霍衫、得到一個類的屬性
2、得到一個類的方法
問題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)建一個對像都會創(chuàng)建printName函數(shù)侯养。而printName方法實際上作用的相同的敦跌,會浪費大量的內(nèi)存
方法2 printName函數(shù)是共用的,這樣避免了重復
問題13: Object.create 有什么作用逛揩?兼容性如何柠傍?
舉列說明
var b = {};
a = Object.create(b);
a.__proto__ === b; // true; 即a的原型為b
es5
問題14: hasOwnProperty有什么作用? 如何使用辩稽?
hasOwnPersonty是Object.prototype的一個方法,可以判斷一個對象是否包含自定義屬性而不是
原型鏈上的惧笛。
舉列說明
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
問題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)建的實列對象。
問題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);
}
Male.prototype = Object.create(Person.prototype);
Male.prototype.getAge = function(){
console.log(this.age);
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.getName(); // 若愚