this 相關(guān)問(wèn)題
1.apply、call 燃观、bind有什么作用叶组,什么區(qū)別
- fn.apply(context , paramArray) , 第一個(gè)參數(shù)context被設(shè)置為this , 其他參數(shù)使用數(shù)組的形勢(shì)阶祭。
- fn.call(context , param1 , param2) , 第一個(gè)參數(shù)context被設(shè)置為this , 其他參數(shù)使用列表的形勢(shì)。
- obj.fn.bind(obj) , 返回一個(gè)新函數(shù)勒奇,并將參數(shù)設(shè)置為函數(shù)的this
2.以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
這個(gè)代碼可以轉(zhuǎn)換成:
var john = {
firstName: "John",
sayHi: func
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi()
所以調(diào)用john對(duì)象的sayHi屬性得到屬性值func , 然后由于func是個(gè)函數(shù)预鬓,后面加了一個(gè)() , 變成執(zhí)行func函數(shù)赊颠,得到結(jié)果為: john: hi!
3.下面代碼輸出什么格二,為什么
func()
function func() {
alert(this)
}
我們也可以寫成這種形式:
func.call(undefined)
function func() {
alert(this)
}
所以它的this是window , 輸出window
4.下面代碼輸出什么
document.addEventListener('click', function(e){
console.log(this); //document , 在事件中劈彪,this指向的是被監(jiān)聽的DOM源對(duì)象
setTimeout(function(){
console.log(this); //setTimeout和setInterval的this都是window
}, 200);
}, false);
5.下面代碼輸出什么,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
使用call的形式調(diào)用func顶猜,john被設(shè)置為func的this沧奴,輸出this,firstName想當(dāng)于輸出john.firstName , 輸出結(jié)果為John。
6.以下代碼有什么問(wèn)題长窄,如何修改
var module= {
bind: function(){
var _this = this;
$btn.on('click', function(){
console.log(this) //this指$btn這個(gè)源DOM
_this.showMsg(); /*調(diào)用showMsg這個(gè)屬性滔吠,需要使用它的對(duì)象module,所以應(yīng)該將context設(shè)置為module,所以如果想使用this
的話挠日,應(yīng)該在module的作用域內(nèi)將this賦予一個(gè)變量疮绷,然后調(diào)用這個(gè)變量就可以使用module作用域內(nèi)的this*/
})
},
showMsg: function(){
console.log('饑人谷');
}
}
原型鏈相關(guā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();
Person函數(shù)聲明的時(shí)候,創(chuàng)造一個(gè)prototype對(duì)象犯犁,此時(shí)這個(gè)對(duì)象是空的属愤,后面給它添加了一個(gè)sayName方法女器,p是一個(gè)構(gòu)造函數(shù)酸役,通過(guò)new得來(lái),在查找sayName時(shí)驾胆,在p的prototype里面找不到涣澡,于是順著它的原型鏈往上找,p的proto指向Person的prototype中的方法sayName , 于是P就可以使用sayName的方法了丧诺。Person的prototype對(duì)象里面的constructor就是Person入桂。
8.上例中,對(duì)對(duì)象 p可以這樣調(diào)用 p.toString()驳阎。toString是哪里來(lái)的? 畫出原型圖?并解釋什么是原型鏈抗愁。
可以調(diào)用,toString是由p的proto屬性指向他更高級(jí)的類呵晚,得來(lái)的蜘腌,p是一個(gè)函數(shù),所以它的類可以是對(duì)象饵隙,所以p的proto找到了對(duì)象的prototype中的toString()方法撮珠,假設(shè)在對(duì)象的prototype當(dāng)中沒(méi)有找到toString,它還會(huì)往更高級(jí)的類上面去找金矛,直到找到為止芯急,如果最后還找不到勺届,就返回一個(gè)undefined,這樣一種依靠proto指向來(lái)尋找方法的這個(gè)過(guò)程娶耍,就像一條鎖鏈免姿,而由于是原型proto在這一過(guò)程當(dāng)中去尋找,所以形象的稱之為原型鏈榕酒。
9.對(duì)String做擴(kuò)展养泡,實(shí)現(xiàn)如下方式獲取字符串中頻率最高的字符
function String(str){
this.str = str;
}
String.prototype = {
constructor: String,
getMostOften: function () {
var strArr = this.str.split('');
var max = 0;
var sum = 0;
var letter = [];
var repeatLetter = false;
for(var i=0; i<strArr.length; i++){
for(var j=0; j<strArr.length; j++){
if(strArr[i] === strArr[j]){
sum++;
}
}
if(sum > max){
max = sum;
letter = [];
letter.push(strArr[i]);
}else if(sum === max){
for(var k=0; k<i; k++){
if(strArr[k] === strArr[i]){
repeatLetter = true;
}
}
if(!repeatLetter){
letter.push(strArr[i]);
}
}
sum = 0;
repeatLetter = false;
}
return letter.join(',');
}
};
var a = new String('11112222233333');
var b = a.getMostOften();
console.log(b);
10.instanceOf有什么作用??jī)?nèi)部邏輯是如何實(shí)現(xiàn)的奈应?
判斷一個(gè)對(duì)象是不是某個(gè)類型的實(shí)例澜掩,如 [1,2,3] instanceOf Array
, 返回結(jié)果為boolean。
它的內(nèi)部邏輯是通過(guò)原型鏈的繼承機(jī)制來(lái)實(shí)現(xiàn)的杖挣,核心代碼如下:
function instanceOf(obj,func) {
if(obj.__proto__ === func.prototype){
return true;
}else{
return false;
}
}
繼承相關(guān)問(wèn)題
11.繼承有什么作用?
一個(gè)對(duì)象可以使用別的對(duì)象的屬性和方法就叫繼承肩榕。
通過(guò)繼承,我們可以避免寫出很多重復(fù)的代碼惩妇,節(jié)約內(nèi)存株汉。
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是添加屬性,方法2是添加方法歌殃。方法1創(chuàng)建一個(gè)構(gòu)造函數(shù)的時(shí)候乔妈,不管你是否使用printName它都會(huì)創(chuàng)造這個(gè)屬性。而方法2的printName是根據(jù)你自己的需要來(lái)決定的氓皱,你不使用這個(gè)方法它就不會(huì)在創(chuàng)建構(gòu)造函數(shù)的時(shí)候創(chuàng)建出來(lái)路召,方法2就起到了節(jié)省內(nèi)存的作用。
13.Object.create 有什么作用波材?兼容性如何股淡?
使用指定的原型對(duì)象及其屬性去創(chuàng)建一個(gè)新的對(duì)象。示例代碼如下:
function person(name, age) {
this.name = name;
this.age = age;
}
person.prototype = {
constructor: person,
sayName: function () {
console.log(this.name);
}
}
function people(sex, professional) {
this.sex = sex;
this.professional = professional;
}
people.prototype = {
constructor: people,
saySex: function () {
console.log(this.sex);
}
}
//現(xiàn)在我指定person的原型對(duì)象和屬性為people.prototype
person.prototype = Object.create(people.prototype);
person.prototype.constructor = person;
console.log(person.prototype);
14. hasOwnProperty有什么作用廷区? 如何使用唯灵?
判斷某個(gè)屬性是否是自身屬性而不是繼承得來(lái)的,如果是則返回true , 如果不是則返回false隙轻。
示例代碼如下:
function person(name, age) {
this.name = name;
this.age = age;
}
person.prototype = {
constructor: person,
sayName: function () {
console.log(this.name);
}
}
if(person.hasOwnProperty('toString')){
console.log(1);
}
if(person.hasOwnProperty('name')){
console.log(2);
}
//輸出結(jié)果為2
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將this變成Male , 而不是Person埠帕。從而使得Male可以繼承Person的屬性。
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);
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.getName();