今天我们要和大家分享几道和重温JavaScript中面向对象部分有关的面试题,即加强对学过内容的理解,又可以为面试做准备。
1.执行下面的代码,返回的结果是true, 那么该如何定义a?
a == 1 && a == 2 && a == 3
解答:a可以是一个对象。当相等运算符的左边是一对象,右边是一个数字时,对象先要做ToPrimitive操作,即先调用valueOf()方法,如果返回基本类型的值就用该值,如果返回的是一个引用类型的值,就调用toString()方法。例如:
var a = {
ownValue : 1,
valueOf: function() {
return this.ownValue++;
}
}
console.log(a == 1 && a == 2 && a == 3);
//true
提示:本题涉及的知识点,我们在重温JavaScript的面向对象部分中一起学习过,你可以点击链接回顾:重温JavaScript(lesson13):面向对象(6)
2.如何判断对象中某个属性是继承而来的?
解答:将in操作符和Object对象的hasOwnProperty()方法组合使用,就能检测一个属性是否是继承属性。我们看代码:
function isInheritProperty(obj,pro) {
return pro in obj && !obj.hasOwnProperty(name);
}
var obj1 = {
name: 'New_Name'
}
var obj2 = Object.create(obj1);
let res = isInheritProperty(obj2, 'name');
console.log(res);
//true
提示:我们给出in操作符和hasOwnProperty()的检测属性的作用说明:
检测方式 | 描述 |
---|---|
in操作符 | 检测属性是不是某对象的自有属性或者继承而来的属性 |
hasOwnProperty | 检测某属性是不是对象的自有属性 |
你可以学习 重温JavaScript(lesson8):面向对象(1)来回顾相关的内容。
3.下面是一段用于对象继承的代码,请指出其中的不足,并提出改进的建议。
function Super(name) {
this.books = [];
this.name = name;
}
function Sub(name) {
}
Sub.prototype = Super.prototype;
解答:这段代码演示了JS通过原型链来实现继承的方式。代码中主要有两个不足之处:第一,不能向超类的构造函数传递参数,也不能使用超类的自有属性 ;第二,在子类的原型中添加属性或者方法会影响超类的原型。如下代码演示了相应问题和解决方案:
针对第一个问题,我们可以在子类的构造函数中显示地调用超类的构造函数。代码如下:
function Super(name) {
this.books = [];
this.name = name;
}
function Sub(name) {
Super.call(this, name);
}
针对第二个问题一种改进的方法是:借用一个空函数中为中介,然后将超类的原型赋值给这个函数的原型,子类的原型再指向这个空函数的实例,这样就能避免修改超类的原型。
function Super(name) {
this.books = [];
this.name = name;
}
//用于解决第一个问题
function Sub(name) {
Super.call(this, name);
}
//用于解决第二个问题
function create(object) {
function Temp() {
}
Temp.prototype = object;
return new Temp();
}
Sub.prototype = create(Super.prototype);
提示:关于JavaScript实现继承的方式,你可以浏览 重温JavaScript(lesson13):面向对象(6) 回顾相应的内容。
4.执行下面的代码,得到的结果是什么?
Array.prototype.isProptotypeOf([1,2])
解答:isProptotypeOf方法用于判断调用此方法的对象是否存在于指定对象的原型链中。此处调用该方法的是数组的原型对象,而方法的实参是一个数组字面量,因此得到的结果为true。
5.用 new 运算符常见对象时,例如使用new Fn(), 具体的创建过程有哪几步?
解答:具体过程大致4步,分别是:
(1)创建一个新对象,它继承自构造函数的原型,即F n.prototype (2)将指定的参数传递给构造函数 (3)将执行上下文绑定到新创建的对象中。(4)如果构造函数有返回值,那么这个返回值将取代第一步中新创建的对象。
提示:我们在函数的调用也就是重温JavaScript(lesson7):函数(3)中分享过的内容:
第一,新创建一个空对象;
第二,该对象作为this参数传递给构造函数,从而作为构造函数的函数上下文;
第三,新创建的对象作为new运算符的返回值。
6.请实现一个isArray()函数,可以判断传入参数是否是数组。
解答:ES5已经为Array对象添加了isArray()方法,专门用于检测对象是否是数组,但是为了兼容非常古老的浏览器有时候还需要自己实现一个方法。代码如下:
function isArray(obj){
if (Array.isArray) {
return Array.isArray(obj);
}
var toString = Object.prototype.toString;
return toString.call(obj) === "[object Array]";
}
let test = [1,2,3];
let res = isArray(test);
console.log(res);
//true
提示:在这里,我们借助了Object对象的toString()方法,返回格式为“[object Type]”的字符串,其中Type是对象的类型,能够检查出来的对象有Number, Array, Date等。另外调用toString方法的时候也不能直接使用而是需要使用call来改变this指针的指向。这道题考查的内容主要是原型的定义以及函数的调用等。你可以参考 重温JavaScript(lesson11):面向对象(4)和重温JavaScript(lesson7):函数(3)的内容。
7.如下代码的输出结果是什么?
var name = "重温JavaScript";
var obj = {
name: 'New_Name',
getName: function() {
return this.name;
},
child: {
name: '重温新知',
getName: function() {
return this.name;
}
}
}
console.log(obj.getName());
console.log(obj.child.getName());
解答:输出 New_Name 重温新知 。本题主要考查this的绑定问题,this代表调用函数的对象,也叫函数上下文。第一个调用getName方法的对象是obj,所以输出它的name属性值;第二个调用getName方法的对象是obj.child,它本身是一个对象所以输出它自己的name属性值。
提示:关于this的讲解在重温JavaScript(lesson7):函数(3)中有较为详细的介绍,如果你对this的内容已经感到生疏或者这道题答错了,请点击查阅和巩固。此题还可以改写:
8.如下代码的输出结果是什么?
var name = "重温JavaScript";
var obj = {
name: 'New_Name',
getName: function() {
return this.name;
}
}
let childName = obj.getName;
let res = childName();
console.log(res);
解答:这段代码在严格模式下会报错,在非严格模式下输出 重温JavaScript 。childName引用了obj对象的getName方法,调用的时候是作为一个普通函数调用的,它的执行上下文是全局对象,在浏览器中就是window, 所以输出全局的na me。
9.如下代码的输出结果是什么?
var name = "重温JavaScript";
var obj = {
name: 'New_Name',
getName: function() {
return this.name;
}
}
function parentName(fn) {
return fn();
}
let res = parentName(obj.getName);
console.log(res);
解答:输出 重温JavaScript。原理同上,只不过是本题中的getName方法本身作为参数传入了parentName。
本次我们就先看这么多题目,主要是和执行上下文this以及和原型相关的题目,希望对大家有所帮助。
如有错误,请不吝指正。温故而知新,欢迎和我一起重温旧知识,攀登新台阶~