問題1: apply、call 捂襟、bind有什么作用咬腕,什么區(qū)別
apply ,call,bind都會改變函數(shù)的執(zhí)行上下文,就是改變函數(shù)的this指向葬荷。
apply和call都是不會改變原函數(shù)涨共,但是參數(shù)不一樣apply的參數(shù)是數(shù)組。
bind是會創(chuàng)建一個新的函數(shù)宠漩,當(dāng)被調(diào)用的時候举反,this還是指向bind()的第一個參數(shù)。而且這個新函數(shù)再次使用call或apply時失效扒吁。
從apply火鼻,bind,call的使用可以從以下代碼思路出發(fā):
var obj = {
x: 81,
getX: function() {
return this.x;
}
};
alert(obj.getX.bind(obj)());
alert(obj.getX.call(obj));
alert(obj.getX.apply(obj));
var age=19;
var k={
age:18,
f:function (){
return this.age;
}
}
var p={
age:39
}
var f2=k.f.bind(p);
console.log(f2());//39,this指向的是p
console.log(f2.call(window));//39雕崩,因為bind()創(chuàng)建的函數(shù)的this還是指向之前bind()第一個參數(shù)p魁索,this始終不變
console.log(f2.apply(k));//39,因為bind()創(chuàng)建的函數(shù)的this還是指向之前bind()第一個參數(shù)p盼铁,this始終不變
var f3=k.f.call(window);
console.log(f3());//error粗蔚,因為call無法產(chǎn)生一個新的函數(shù)
問題2: 以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
輸出的是John
可以這么思考 john.sayHi().call(john);
問題3: 下面代碼輸出什么,為什么
func()
function func() {
alert(this)
}
輸出的是window
思考:func().call(window);this 就是call函數(shù)的參數(shù)饶火。
問題4:下面代碼輸出什么
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
執(zhí)行結(jié)果:
console.log(this)輸出的是 document
而setTimeout種輸出的console.log(this)
輸出是window
因為setTimeout的this無論在哪個位置指向的都是window
問題5:下面代碼輸出什么鹏控,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
輸出的結(jié)果是:
John 因為func.call(john)中將this改為了指向john對象
問題6: 以下代碼有什么問題致扯,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
問題是this.showMsg()中this的指向問題
修改如下:
$btn=$("button");
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this);
this.showMsg();
}.bind(this))
},
showMsg: function(){
console.log('饑人谷');
}
}
module.showMsg();
https://jsbin.com/dazigurisi/5/edit?html,js,console,output
總結(jié)this的使用:
大部分的函數(shù)調(diào)用都將call方法省略了,而call的理解就如同一個對象調(diào)用一個方法当辐,而this則是只call的第一個參數(shù)抖僵。
修改setTImeout或者setInterval的this用bind的方法
網(wǎng)址為:https://stackoverflow.com/questions/11366643/how-do-i-change-scope-of-this-in-setinterval-and-settimeout-functions
修改click的this指向用bind方法如下:
網(wǎng)址為:https://stackoverflow.com/questions/5490448/how-do-i-pass-the-this-context-into-an-event-handler
一篇方方介紹了JS 里為什么會有 this
原型鏈相關(guān)問題
方方的一篇關(guān)于new 到底是干什么的
https://zhuanlan.zhihu.com/p/23987456
解釋:關(guān)于new到底是干什么的,我在方方的一篇文章中找到了以下觀點(diǎn):
不用創(chuàng)建臨時對象缘揪,因為 new 會幫你做(你使用「this」就可以訪問到臨時對象)耍群;
不用綁定原型,因為 new 會幫你做(new 為了知道原型在哪找筝,所以指定原型的名字為 prototype)世吨;
不用 return 臨時對象,因為 new 會幫你做呻征;
不要給原型想名字了,因為 new 指定名字為 prototype罢浇。
總結(jié)下來就是new其實(shí)就是返回了一個對象陆赋,這個對象在new的過程中自動創(chuàng)建了一個_ _proto _ 屬性,這個對象中會復(fù)制構(gòu)造函數(shù)自己所擁有的內(nèi)容嚷闭。同時 _proto _ _這個屬性會指向構(gòu)造函數(shù)的原型對象攒岛。
問題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();
關(guān)系為:
p._ _ proto _ _ ==Peroson.prototype ;
Person.prototype.constructor ==Person;
p.__ proto__.constructor==Person;
Person.prototype.__ proto __ ==Object.prototype;
p. __ proto__.__ proto __ ==Object.prototype;
p. __ proto__.__ proto __ ==Person.prototype.__ proto __;
Object. __ proto __ =null;
問題8: 上例中,對對象 p可以這樣調(diào)用 p.toString()凌那。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈兼雄。
toSting()是object.prototype中的
P先從proto中查找是否有toString()方法,如果沒有就從p.proto.proto中查找帽蝶,一直沿著原型鏈查找赦肋,直到object的prototype中找到toString方法
問題9:對String做擴(kuò)展,實(shí)現(xiàn)如下方式獲取字符串中頻率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現(xiàn)了5次
代碼如下:
var str = 'ahbbccdeddddfg';
String.prototype.getMostOften=function()
{
var str={};
var key;
for(var i=0;i<this.length;i++)
{
key=this[i];
if(str[key])
{
str[key]++;
}
else
{
str[key]=1;
}
}
var max=0,maxkey;
for(var key in str)
{
if(str[key]>max)
{
max=str[key];
maxkey=key;
}
}
return ("出現(xiàn)最多的字符是:"+maxkey+","+"共出現(xiàn)了"+max+"次");
}
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現(xiàn)了5次
問題10: instanceof有什么作用励稳?內(nèi)部邏輯是如何實(shí)現(xiàn)的佃乘?
instanceof操作符判斷一個對象是不是某個類的實(shí)例
instanceof依據(jù)原型鏈上的 _ proto _屬性指向了構(gòu)造函數(shù)的prototype
function _instanceof(fn,fn2)
{
var pointer=fn.__proto__;
while(pointer)
{
if(pointer==fn2.prototype)
{
return true;
}
else
{
pointer=pointer.__proto__;
}
}
return false;
}
var arr=[1,2];
var fn2=Object;
console.log(_instanceof(arr, Array));
console.log(_instanceof(arr, fn2));
問題11:繼承有什么作用?
繼承是指獲取類的屬性,類的方法
作用有
1.子類通過繼承了父類的屬性和方法驹尼,就不需要重復(fù)代碼了
2.子類可以重寫和擴(kuò)展父類的屬性和方法趣避,但是又不會影響父類
問題12: 下面兩種寫法有什么區(qū)別?
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);
第一種寫法是:p1的內(nèi)部有name,sex屬性和printName方法扶欣,p1的 _ _ proto _ _ 指向People的prototype對象
第二種寫法是p1的內(nèi)部有name鹅巍,sex屬性,p1的 _ _ proto_ _指向People的prototype對象,printName方法存放在Person的prototype對象中
問題13: Object.create 有什么作用千扶?兼容性如何?
object.create()創(chuàng)建一個新對象骆捧,并且該對象的原型指向Object.create()的第一個參數(shù)對象澎羞。
var f={a:1,b:3};
var s=Object.create(f);
console.log(s.__proto__==f);
兼容性:
凡實(shí)現(xiàn)ECS5標(biāo)準(zhǔn)的瀏覽器,都能使用敛苇,IE9以上
問題14: hasOwnProperty有什么作用妆绞? 如何使用?
hasOwnProperty是判斷一個屬性是否是對象自己所擁有的屬性而不是原型對象中的枫攀。
var buz = {
fog: 'stack'
};
for (var name in buz) {
if (buz.hasOwnProperty(name)) {
alert("this is fog (" + name + ") for sure. Value: " + buz[name]);
}
else {
alert(name); // toString or something else
}
}
問題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作用是讓Male繼承Person的name括饶,sex屬性
問題16: 補(bǔ)全代碼,實(shí)現(xiàn)繼承
function Person(name, sex){
// todo ...
}
Person.prototype.getName = function(){
// todo ...
};
function Male(name, sex, age){
//todo ...
}
//todo ...
Male.prototype.getAge = function(){
//todo ...
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
修改代碼如下:
function Person(name, sex){
this.name=name;
this.sex=sex;
}
Person.prototype.printName = function(){
console.log(this.name);
};
function Male(name, sex, age){
Person.call(this,name,sex);
this.age=age;
}
//將Male的原型對象指向Person来涨,使用create方法是創(chuàng)建一個新的對象图焰,且新函數(shù)的原型對象與Person的原型對象相同。這樣做的原因是為了防止
Male修改的時候影響父元素的原型對象蹦掐。
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();
總結(jié):對于this的思考技羔,this就是call函數(shù)傳入的第一個參數(shù)。函數(shù)調(diào)用的時候引入call思考就會很任意的明白this的指向了卧抗。