问题1: apply、call 、bind有什么作用,什么区别
- bind
返回一个新函数,并且使函数内部的 this 为传入的第一个参数
- call
调用一个函数,为其指定 this , 分别提供参数
- apply
调用一个函数,为其指定 this ,参数以数组形式传入
var value = 2;
function sum(a, b) {
console.log( this.value + a + b )
//return this.value + a +b
}
//直接调用
sum(5,6) // 2+5+6 =13
//apply 指定this ,参数以数组的形式传递
var obj1 = {
value: 3
}
sum.apply(obj1, [5, 6]) // 3+5+6
//call 指定 this ,分别提供参数
var obj2 = {
value: 1
}
sum.call(obj2, 5, 6) // 2+5+6
//bind 指定 this ,返回一个新的函数
var obj3 = {
value: 7
}
var newSum = sum.bind(obj3)
newSum(5,6) // 7+5+6
问题2: 以下代码输出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
输出结果 John:hi! 因为这里的sayHi 是 john 调用的,所以 this 指向
join 对象
问题3: 下面代码输出什么,为什么
func()
function func() {
alert(this)
}
在浏览器运行时, this 是指window ,因此,代码运行后,会弹窗显示 window 对象。
问题4:下面代码输出什么
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
第一个 this
是指 document
, 因为事件绑定自动把this
指向对应元素。第二个 this
为 window
,因为匿名函数的执行是在window
全局下的
问题5:下面代码输出什么,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
弹窗显示 Jonhn
,因为call
指定this
为john
对象。
问题6: 以下代码有什么问题,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) // this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}
this
指调用事件的 DOM 元素,要想让 this
指向对象本身,可以保存原来的this
var module= {
bind: function(){
var _this = this
$btn.on('click', function(){
console.log(self)
self.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();
Person
是构造函数, prototype
是构造函数的共有属性。 p
是Person
的实例,该实例有__proto__
对象指向Person.prototype
。constructor
表示该实例的构造器,指向Person
。
p.__proto__.constructor === Person.prototype.constructor === Person
问题8: 上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。
p.__proto__ === Person.prototype
Person.prototype.__proto__ === Object.protyotype
toString
是Object的prototype上的方法,所以p
可以调用p.toString()
问题9:对String做扩展,实现如下方式获取字符串中频率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
String.prototype.getMostOften = function(){
var arr = {};
// 找到字符串里所有字母他的个数保存至对象 arr。
for(i=0; i<this.length; i++){
if (arr[ this[i] ]){
arr[ this[i] ]++;
}else {
arr[ this[i] ] = 1;
}
}
var max = 0, maxStr;
// 遍历对象 arr 把出现次数最大值赋值给 max;
for(var key in arr){
if (arr[key] > max){
max = arr[key];
maxStr = key;
}
}
return maxStr + ",因为 " + maxStr + " 出现了" + max + "次";
};
问题10: instanceOf有什么作用?内部逻辑是如何实现的?
instanceOf用来判断一个对象是是否是一个构造函数的实例。内部是通过判断instance.__proto__ === Object.prototype
是否相同来实现的,假如当前不相等,就会根据原型链往上找,instance.__proto__.__proto__ === Object.prototype
,直到null,找到就返回true,否则为false。
问题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
作为对象的自有方法定义,对象实例化后自身拥有这个方法,每次new
出来实例,都会产生新的属性和方法,占用过多不必要的内存。
方法二: 将printName
放在构造方法的prototype
属性中,实例化对象可以通过原型链查找调用这个方法使用原型的好处可以让所有对象实例共享它所包含的属性和方法。每次new
出来的实例,会产生新的属性,但方法都在共有的属性原型链(prototype)上,节省内存。
问题13: Object.create 有什么作用?兼容性如何?
Object.create()
方法会使用指定的原型对象及其属性去创建一个新的对象,实现继承。
Student.prototype = Object.create(Person.prototype);
问题14: hasOwnProperty有什么作用? 如何使用?
hasOwnProperty()
方法返回一个布尔值,指示对象自身属性中是否具有指定的属性(是自身属性,不包含prototype
)。
function Person(){
this.name = 'jack'
}
Person.prototype.commonName = 'Person'
var a = new Person()
console.log(a.hasOwnProperty('name'))
问题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;
}
作用是将Person
中的this
作用域指向Male
,实现构造函数继承
问题16: 补全代码,实现继承
function Person(name, sex) {
this.name = name
this.sex = sex
}
Person.prototype.printName = function() {
console.log('My name is '+ 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(){
return this.age
}
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();