this
1,apply、call 、bind有什么作用,什么區別
- apply/call:調用一個函數,傳入函數執行上下文及參數
fn.call(context,param1,param2...);
fn.apply(context,paramArray;
語法很簡單,第一個參數都是希望設置的this對象,不同之處在于call方法接收參數列表,而apply接收參數數組
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
fn4.apply(obj4,[3,4]); //207
- bind:返回一個函數,并且使函數內部的this為傳入的第一個參數
var obj1 = {
name: 'deejay',
age: 20,
fn: function () {
console.log(this);
}
};
var obj3 = {
a: 3,
}
var fn3 = obj1.fn.bind(obj3);
fn3(); //obj3
apply/call是指的調用一個函數,傳入這個函數的執行上下文和參數。而bind是指的是返回一個函數,并且使函數內部的this為傳入的第一個參數。
call/apply在函數調用時使用,bind在函數聲明時使用。 bind() 方法會返回執行上下文被改變的函數而不會立即執行,而call/apply是直接執行該函數。
2,以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()//John: hi!
3,以下代碼輸出什么?
func()
function func() {
alert(this) //window
}
可以看做window.func();
4,下面代碼輸出什么
document.addEventListener('click', function(e){
console.log(this); //#document
setTimeout(function(){
console.log(this);//window
}, 200);
}, false);
setTimeoutl這個方法執行的函數this是全局對象,
在事件處理程序中this代表事件源DOM對象
5,下面代碼輸出什么
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john);//John
使用了call方法,調用了func(),并且將內部this修改為john
6,以下代碼有什么問題,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('deejay');
}
}
問題出在了在事件處理程序中this代表事件源DOM對象,所以點擊的時候的this是當前點擊的DOM元素,沒有showMsg這個方法,解決方法如下:
var module= {
bind: function(){
var self = this;
console.log(self);
$btn.on('click', function(){
console.log(this); //this指的是當前觸發點擊事件的DOM元素
self.showMsg()
})
},
showMsg: function(){
console.log('deejay');
}
}
這里設置一個self保存有showMsg()方法的this,即module,然后調用showMsg
原型鏈
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("deejay")
p.sayName();//My name is :deejay
本例中,Person作為構造函數,創建了它的實例p,實例p存在一個屬性__proto__,等于Person.prototype,而Person中存在一個Person.prototype對象,其有一個屬性constructor,這個屬性又指向Person。
即有:
p.__proto__ === Person.prototype;
Person.prototype.constructor === Person;
8,上例中,對對象 p可以這樣調用 p.toString()。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈。
原型圖如圖所示,當調用p的toString()時,會先在實例中尋找,如果找不到,再到p.__proto__屬性中,即Person.prototype中尋找,當在Person.prototype中尋找不到時,會到Person.prototype.__proto__中也就是Object.prototype中尋找,然后就尋找到了toString()。
所以整個過程為p 到 p.__proto__ 再到 p.__proto__.__proto__中,逐級向上查找即為原型鏈。
9,對String做擴展,實現如下方式獲取字符串中頻率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現了5次
給str的構造函數String的prototype添加函數
String.prototype.getMostOften = function () {
//等價于 str.__proto__.getMostOften = ...
var dict = {};
var count;
var maxvalue = 0;
for (var i = 0; i < this.length; i ++) {
if (dict[this[i]]) {
dict[this[i]]++;
}
else {
dict[this[i]] = 1;
}
}
for (var key in dict) {
if (dict[key] > maxvalue) {
maxvalue = dict[key];
count = key;
}
}
return count;
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現了5次
10, instanceOf有什么作用?內部邏輯是如何實現的?
instanceOf用來判斷某個對象是否是某函數的實例
主要實現邏輯為,先判斷p.__proto__ 是否為Person.prototype,如果不是,接著判斷p.__proto__ .__proto__ 是否為Person.prototype,...直到為null返回false,如果在查找途中發現是Person.prototype的實例,返回true
繼承
11,繼承有什么作用?
繼承是指一個對象直接使用另一對象的屬性和方法。
如果要創建一個子類,不用重新復制一遍父類的代碼,可以直接繼承然后進行添加子類自己的屬性和方法
12,下面兩種寫法有什么區別?
//方法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('deejay', 21);
方法1是在每次創建一個實例的時候都會相應的給實例也創建一個printName(),如果創建了多個實例的話每個實例都會有一個相同的printName()。
方法2是在構造函數的prototype中添加一個printName(),作為所有實例的公共方法,這樣多個所有被創建的實例自身只有自身的屬性,而printName()是公用的,只有一個,節省了內存。
13, Object.create 有什么作用?兼容性如何?
Object.create() 方法會使用指定的原型對象及其屬性去創建一個新的對象。
Object.create是ES5方法
14, hasOwnProperty有什么作用? 如何使用?
是Object.prototype的一個方法,可以判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性,hasOwnProperty是JS中唯一一個處理屬性但是不查找原型鏈的函數
function Person(name,age) {
this.name = name;;
this.age = age;
}
Person.prototype.sayName = function () {
console.log(this.name);
}
var p1 = new Person('deejay',21);
p1.hasOwnProperty('name');//true
p1.hasOwnProperty('age');//true
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;
}
這里的call即為在Male構造函數內部調用Person構造函數,將Male創建的實例this傳給Person,達到的效果就是復制了Person構造函數中的所有屬性
16,補全代碼,實現繼承
function Person(name, sex){
// todo ...
}
Person.prototype.getName = function(){
// todo ...
};
function Male(name, sex, age){
//todo ...
}
//todo ...
Male.prototype.getAge = function(){
//todo ...
};
var deejay= new Male('deejay', '男', 21);
deejay.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); // 復制Person內部的屬性
this.age = age;
}
Male.prototype = Object.create(Person.prototype); // 實現方法的繼承
Male.prototype.getAge = function(){
console.log(this.age)
};
var deejay = new Male('deejay', '男', 21);
deejay.printName();//deejay