問題1: apply、call 、bind有什么作用,什么區別
apply ,call,bind都會改變函數的執行上下文,就是改變函數的this指向。
apply和call都是不會改變原函數,但是參數不一樣apply的參數是數組。
bind是會創建一個新的函數,當被調用的時候,this還是指向bind()的第一個參數。而且這個新函數再次使用call或apply時失效。
從apply,bind,call的使用可以從以下代碼思路出發:
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()創建的函數的this還是指向之前bind()第一個參數p,this始終不變
console.log(f2.apply(k));//39,因為bind()創建的函數的this還是指向之前bind()第一個參數p,this始終不變
var f3=k.f.call(window);
console.log(f3());//error,因為call無法產生一個新的函數
問題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函數的參數。
問題4:下面代碼輸出什么
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
執行結果:
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)
輸出的結果是:
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
總結this的使用:
大部分的函數調用都將call方法省略了,而call的理解就如同一個對象調用一個方法,而this則是只call的第一個參數。
修改setTImeout或者setInterval的this用bind的方法
網址為:https://stackoverflow.com/questions/11366643/how-do-i-change-scope-of-this-in-setinterval-and-settimeout-functions
修改click的this指向用bind方法如下:
網址為:https://stackoverflow.com/questions/5490448/how-do-i-pass-the-this-context-into-an-event-handler
一篇方方介紹了JS 里為什么會有 this
原型鏈相關問題
方方的一篇關于new 到底是干什么的
https://zhuanlan.zhihu.com/p/23987456
解釋:關于new到底是干什么的,我在方方的一篇文章中找到了以下觀點:
不用創建臨時對象,因為 new 會幫你做(你使用「this」就可以訪問到臨時對象);
不用綁定原型,因為 new 會幫你做(new 為了知道原型在哪,所以指定原型的名字為 prototype);
不用 return 臨時對象,因為 new 會幫你做;
不要給原型想名字了,因為 new 指定名字為 prototype。
總結下來就是new其實就是返回了一個對象,這個對象在new的過程中自動創建了一個_ _proto _ 屬性,這個對象中會復制構造函數自己所擁有的內容。同時 _proto _ _這個屬性會指向構造函數的原型對象。
問題7:有如下代碼,解釋Person、 prototype、proto、p、constructor之間的關聯。
function Person(name){
this.name = name;
}
Person.prototype.sayName = function(){
console.log('My name is :' + this.name);
}
var p = new Person("若愚")
p.sayName();
關系為:
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可以這樣調用 p.toString()。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈。
toSting()是object.prototype中的
P先從proto中查找是否有toString()方法,如果沒有就從p.proto.proto中查找,一直沿著原型鏈查找,直到object的prototype中找到toString方法
問題9:對String做擴展,實現如下方式獲取字符串中頻率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現了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 ("出現最多的字符是:"+maxkey+","+"共出現了"+max+"次");
}
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現了5次
問題10: instanceof有什么作用?內部邏輯是如何實現的?
instanceof操作符判斷一個對象是不是某個類的實例
instanceof依據原型鏈上的 _ proto _屬性指向了構造函數的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.子類通過繼承了父類的屬性和方法,就不需要重復代碼了
2.子類可以重寫和擴展父類的屬性和方法,但是又不會影響父類
問題12: 下面兩種寫法有什么區別?
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的內部有name,sex屬性和printName方法,p1的 _ _ proto _ _ 指向People的prototype對象
第二種寫法是p1的內部有name,sex屬性,p1的 _ _ proto_ _指向People的prototype對象,printName方法存放在Person的prototype對象中
問題13: Object.create 有什么作用?兼容性如何?
object.create()創建一個新對象,并且該對象的原型指向Object.create()的第一個參數對象。
var f={a:1,b:3};
var s=Object.create(f);
console.log(s.__proto__==f);
兼容性:
凡實現ECS5標準的瀏覽器,都能使用,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: 補全代碼,實現繼承
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方法是創建一個新的對象,且新函數的原型對象與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();
總結:對于this的思考,this就是call函數傳入的第一個參數。函數調用的時候引入call思考就會很任意的明白this的指向了。