1.apply迎捺、call 、bind有什么作用,什么區(qū)別
call apply的作用:調(diào)用一個(gè)函數(shù)炸站,傳入函數(shù)執(zhí)行上下文及參數(shù)
第一個(gè)參數(shù)都是希望設(shè)置的this對象,不同之處在于call方法接收參數(shù)列表疚顷,而apply接收參數(shù)數(shù)組
-
call
fn.call(context, param1, param2...)
-
apply
fn.apply(context, paramArray)
例子:
//call()
window.name = "1";
var a = {name: "2"};
function sayName(){
alert(this.color);
}
sayName(); //1
sayName.call(this); // 1
sayName.call(a); //2
//apply()
var numbers = [1,5,6,2,3,7,8]
var max = Math.max.apply(null,numbers) //8
bind的作用:返回一個(gè)新函數(shù)旱易,并且使函數(shù)內(nèi)部的this為傳入的第一個(gè)參數(shù)
例子:
var obj1 = {
name: 'Byron',
fn : function(){
console.log(this);
}
};
obj1.fn(); //obj1
var fn2 = obj1.fn;
fn2(); //window
var fn3 = obj1.fn.bind(obj1);
fn3(); //obj1
2.以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi() //John:hi!
輸出John:hi!
john對象調(diào)用sayHi()方法,this指向john對象
3. 下面代碼輸出什么腿堤,為什么
func()
function func() {
alert(this)
}
輸出window
func()等價(jià)于window.func()阀坏,window對象調(diào)用func()方法,this指向window對象
4.下面代碼輸出什么笆檀?
document.addEventListener('click', function(e){
console.log(this); //document忌堂,點(diǎn)擊事件回調(diào)方法執(zhí)行時(shí),this指向document
setTimeout(function(){
console.log(this); //window酗洒,定時(shí)器回調(diào)函數(shù)執(zhí)行時(shí)士修,this指向window
}, 200);
}, false);
5.下面代碼輸出什么,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john) //John樱衷, func.call(john)方法執(zhí)行時(shí)棋嘲,由于傳入了john對象作為參數(shù),func()方法中的this指向john對象
6.以下代碼有什么問題矩桂,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么 this指$btn對象
this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
問題:在$btn的點(diǎn)擊回調(diào)函數(shù)中沸移,this.showMsg()方法執(zhí)行時(shí)會(huì)報(bào)錯(cuò),this.showMsg is not a function
修改:
var module= {
bind: function(){
let self = this; //self對象指向module對象
$btn.on('click', function(){
console.log(this) //this指什么 this指$btn對象
self.showMsg(); //調(diào)用module的showMsg()方法
})
},
showMsg: function(){
console.log('饑人谷');
}
}
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();
Person是構(gòu)造函數(shù)
prototype是Person的原型對象,prototype對象中有一個(gè)屬性contructor(表示構(gòu)造函數(shù))在辆,contructor指向Persion構(gòu)造函數(shù)
p是通過Person構(gòu)造函數(shù)生成的對象
p對象的proto原型對象指向Person構(gòu)造函數(shù)的原型证薇,所以p.sayName()實(shí)際上是調(diào)用Person原型對象中的sayName方法
8.問題8: 上例中,對對象 p可以這樣調(diào)用 p.toString()匆篓。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈浑度。
p會(huì)找自己的toString方法,如果沒有找到鸦概,會(huì)沿著proto屬性繼續(xù)到構(gòu)造函數(shù)Person的prototype里找toString方法箩张,如果還未找到,再繼續(xù)往Person.prototype的proto即Object.prototype找toString方法窗市,最后找到toString()方法先慷。
原型鏈:由于原型對象本身也是對象,而每個(gè)javascript對象都有一個(gè)原型對象咨察,每個(gè)對象都有一個(gè)隱藏的proto屬性论熙,原型對象也有自己的原型,而它自己的原型對象又可以有自己的原型摄狱,這樣就組成了一條鏈脓诡,這個(gè)就是原型鏈。在訪問對象的屬性時(shí)媒役,如果在對象本身中沒有找到祝谚,則會(huì)去原型鏈中查找,如果找到酣衷,直接返回值交惯;如果整個(gè)鏈遍歷且沒有找到需要的屬性,則返回undefined鸥诽。原型鏈一般實(shí)現(xiàn)為一個(gè)鏈表商玫,這樣就可以按照一定的順序來查找箕憾。
9.對String做擴(kuò)展牡借,實(shí)現(xiàn)如下方式獲取字符串中頻率最高的字符
var str = 'ahbbccdeddddfg';
Object.prototype.getMostOften = function() {
let strArr = this.split('')
//例子:[{letter: a, times: 1}];
let mostLetterArray = []
let mostTimes = 0
let mostLetterIndex = 0
for (let i = 0, len = strArr.length; i < len; i++) {
let isExist = false;
for (let j = 0, len2 = mostLetterArray.length; j < len2; j++) {
if (mostLetterArray[j].letter === strArr[i]) {
mostLetterArray[j].times += 1;
isExist = true;
break;
}
}
if (!isExist) {
mostLetterArray.push({
letter: strArr[i],
times: 1
})
}
}
for (let i = 0, len = mostLetterArray.length; i < len; i++) {
if (mostLetterArray[i].times > mostTimes) {
mostTimes = mostLetterArray[i].times
mostLetterIndex = i
}
}
return mostLetterArray[mostLetterIndex].letter + ',因?yàn)? + mostLetterArray[mostLetterIndex].letter + ' 出現(xiàn)了' + mostLetterArray[mostLetterIndex].times + '次'
}
var ch = str.getMostOften();
console.log(ch); //d , 因?yàn)閐 出現(xiàn)了5次
10. instanceOf有什么作用?內(nèi)部邏輯是如何實(shí)現(xiàn)的袭异?
instanceOf 作用是檢查對象的構(gòu)造函數(shù)
instanceof 運(yùn)算符用來測試一個(gè)對象在其原型鏈中是否存在一個(gè)構(gòu)造函數(shù)的 prototype 屬性钠龙。
例子:
// 定義構(gòu)造函數(shù)
function C(){}
function D(){}
var o = new C();
// true,因?yàn)?Object.getPrototypeOf(o) === C.prototype
o instanceof C;
// false,因?yàn)?D.prototype不在o的原型鏈上
o instanceof D;
o instanceof Object; // true,因?yàn)镺bject.prototype.isPrototypeOf(o)返回true
C.prototype instanceof Object // true,同上
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);
方法1: printName方法放在了構(gòu)造函數(shù)中并指向一個(gè)匿名函數(shù),因此每個(gè)person實(shí)例的printName方法都會(huì)單獨(dú)占用內(nèi)存咬腋,但由于printName方法的功能是一樣的羹膳,可以使用同一個(gè)printName方法達(dá)到減少內(nèi)存占用
方法2: printName方法放在了Person的原型對象中,當(dāng)person實(shí)例調(diào)用printName方法時(shí),會(huì)沿著原型鏈,找到Person的原型對象,使用Person的原型對象中的printName方法,因此每個(gè)person實(shí)例都可以調(diào)用printName方法,但是這些printName方法都指的是Person的原型對象中的printName方法,達(dá)到減少內(nèi)存占用的目的
13.Object.create 有什么作用?兼容性如何根竿?
Object.create() 方法使用指定的原型對象和其屬性創(chuàng)建了一個(gè)新的對象陵像。即傳入類的原型后,可以克隆原型對象參數(shù)并返回一個(gè)新的對象
例子:
//Shape - 父類
function Shape() {
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info("Shape moved.");
};
// Rectangle - 子類
function Rectangle() {
Shape.call(this); //call 父類的 constructor.
}
Rectangle.prototype = Object.create(Shape.prototype);
var rect = new Rectangle();
rect instanceof Rectangle //true.
rect instanceof Shape //true.
rect.move(1, 1); //Outputs, "Shape moved."
兼容性:
| Chrome | Firefox (Gecko) | Internet Explorer | Opera | Opera |
| --- | --- | --- |
| 5 | 4.0 (2) | 9 | 11.60 | 5 |
14. hasOwnProperty有什么作用寇壳? 如何使用醒颖?
hasOwnProperty() 方法會(huì)返回一個(gè)布爾值,指示對象是否具有指定的屬性作為自身(不繼承)屬性壳炎。
所有繼承了 Object
的對象都會(huì)繼承到 hasOwnProperty
方法泞歉。這個(gè)方法可以用來檢測一個(gè)對象是否含有特定的自身屬性;和 in
運(yùn)算符不同匿辩,該方法會(huì)忽略掉那些從原型鏈上繼承到的屬性腰耙。
例子:
o = new Object();
o.prop = 'exists';
function changeO() {
o.newprop = o.prop;
delete o.prop;
}
o.hasOwnProperty('prop'); // 返回 true
changeO();
o.hasOwnProperty('prop'); // 返回 false
o = new Object();
o.prop = 'exists';
o.hasOwnProperty('prop'); // 返回 true
o.hasOwnProperty('toString'); // 返回 false
o.hasOwnProperty('hasOwnProperty'); // 返回 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;
}
通過call()方法,在將創(chuàng)建的male實(shí)例的環(huán)境下調(diào)用了Person構(gòu)造函數(shù)铲球,這樣就會(huì)在新創(chuàng)建的male對象上執(zhí)行Person的構(gòu)造方法把屬性賦值到自己內(nèi)部沟优,這樣每個(gè)male實(shí)例都會(huì)具有自己的name和sex屬性。
16. 補(bǔ)全代碼睬辐,實(shí)現(xiàn)繼承
function Person(name, sex) {
this.name = name;
this.sex = sex;
}
Person.prototype.getName = function() {
return this.name;
};
function Male(name, sex, age) {
Person.call(this, name, sex);
}
function inherit(superType, subType) {
var _prototype = Object.create(superType.prototype);
_prototype.constructor = subType;
subType.prototype = _prototype;
}
inherit(Person, Male);
Male.prototype.getAge = function() {
return this.age;
};
Male.prototype.printName = function() {
console.log(this.getName());
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();