1. apply、call 、bind有什么作用,什么区别?
call ,apply的作用:调用一个函数,传入函数执行上下文及参数
第一个参数都是希望设置的this对象,不同之处在于call方法接收参数列表,而apply接收参数数组
-
call
fun.call(thisArg[, arg1[, arg2[, ...]]])
-
apply
fun.apply(thisArg, [argsArray])
例子:
//call()
window.name = "1";
var a = {name: "2"};
function sayName(){
alert(this.name);
}
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的作用:返回一个新函数,并且使函数内部的this为传入的
第一个参数
例子:
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! //因为func赋给了john对象的sayHi属性,执行john.sayHi() 时 是在john对象上调用的,此时的上下文this是john了.
3. 下面代码输出什么,为什么?
func() //执行函数,当前执行环境是window,alert [object Window] function func() { alert(this) }
4. 下面代码输出什么?
document.addEventListener('click', function(e){ console.log(this); //document,点击事件回调方法执行时,this指向document setTimeout(function(){ console.log(this); //window,定时器回调函数执行时,this指向window }, 200); }, false);
5. 下面代码输出什么,why?
var john = { firstName: "John" } function func() { alert( this.firstName ) } func.call(john) //John, func.call(john)方法执行时,由于传入了john对象作为参数,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的点击回调函数中,this.showMsg()方法执行时会报错,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(); //调用module的showMsg()方法 }) }, showMsg: function(){ console.log('饥人谷'); } }
原型链相关问题
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是Person的实例,所以继承Person原型链上的属性和方法。 //关联: Person.prototype.constructor == Person, Person.prototype == p.__proto__, p.__proto__.constructor == Person, Person.prototype.__proto__ == Object.prototype, Object.prototype.constructor == Object, Object.prototype.__proto__ == null
8. 上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。
答:构造函数的原型自带一个指针指向object的原型,因而toString是从object的原型里继承而来。
原型链:JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做proto的内置属性,用于指向创建它的函数对象的原型对象prototype。在访问一个对象属性的时候,如果对象本身没有找到这个属性,就会沿着原型链一层一层的寻找。
9. 对String做扩展,实现如下方式获取字符串中频率最高的字符
var str = 'ahbbccdeddddfg'; String.prototype.getMostOften = function(){ var obj = {}; for(var i=0,k;i<this.length;i++){ k = this[i]; if(obj[k]){ obj[k]++ }else{ obj[k] = 1 } } console.log(obj);
`var max = 0,key;
for(var k in obj){
if(obj[k]>max){
max = obj[k];
key = k;
}
}
return key;
}
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次`
10. instanceOf有什么作用?内部逻辑是如何实现的?
instanceof运算符返回一个布尔值,表示指定对象是否为某个构造函数的实例。instanceof的原理是检查原型链,对于那些不存在原型链的对象,就无法判断。
var arr = [1, 2, 3]; arr instanceof Array; //true 其实是判断arr.__proto__===Array.prototype arr instanceof Object; //true 判断arr.__proto__.__proto__===Object.prototype
继承相关问题
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('若愚', 27); //printName:一个写在构造函数内部的实例对象上。另一个写在构建函数的prototype对象上。 //前者在每生成一个实例之后实例的printName就新占用内存。 //后者每生成一个实例后会共享构造函数prototype对象上的printName方法,以达到节省内存的效果;
13.Object.create 有什么作用?兼容性如何?
Object.create() 方法使用指定的原型对象和其属性创建了一个新的对象。即传入类的原型后,可以克隆原型对象参数并返回一个新的对象
例子:
//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."
兼容性:各大浏览器的最新版本(包括IE9)都兼容了这个方法。如果遇到老式浏览器,可以用下面的代码兼容:
if(!Object.create){ Object.create = function(obj){ function F(){}; F.prototype = obj; return new F(); } }
14. hasOwnProperty有什么作用? 如何使用?
答:
对象实例的hasOwnProperty方法返回一个布尔值,用于判断某个属性定义在对象自身,还是定义在原型链上。
var people = { name:'teren' } people.hasOwnProperty('name')//true people.hasOwnProperty('toString')//false Object.getPrototypeOf(people).hasOwnProperty('toString')//true
15.如下代码中call的作用是什么?
function Person(name, sex){ this.name = name; this.sex = sex; } function Male(name, sex, age){ Person.call(this, name, sex); //这里的 call 有什么作用 //构造函数Person在构造函数Male作用域下执行,以实现构造函数的继承; this.age = age; }
16. 补全代码,实现继承
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); this.age = age; } //function inherit(superType, subType) { var _prototype = Object.create(superType.prototype); _prototype.constructor = subType; subType.prototype = _prototype; } inherit(Person, Male);// Male.prototype = Object.create(Person.prototype); Male.prototype.constructor = Male; Male.prototype.getAge = function(){ return this.age }; Male.prototype.getAge = function(){ console.log(this.name) }; var ruoyu = new Male('若愚', '男', 27); ruoyu.getName();