1、OOP 指什么?有哪些特性?
OOP是object oriented programming - 面向对象编程的缩写。 它具有三大特性: 封装、继承、多态。
- 封装:隐藏对象的属性和实现细节,仅对外公开接口
-
继承:子类能继承父类的属性和方法
子类能添加新的属性和方法,还能重写父类的属性和方法 - 多态:指同一个实体同时具有多种形式,同一操作作用于不同对象,可以有不同的解释,产生不同的执行结果。
在面向对象程序设计中有两个重要概念
类:类是对现实生活中一类具有共同特征的事物的抽象
对象:对象是类的实例,对象包含属性和方法,属性是需要记忆的信息,方法是对象能够提供的服务。
2、如何通过构造函数的方式创建一个拥有属性和方法的对象?
属性可以通过this.xxx = xxx
的方式直接赋值,方法可以通过this.prototype.xxx = function(){}
的方式创建
//定义构造函数,默认命名第一个字母为大写
function People(name,age){
this.name = name
this.age = age
}
people.prototype.slogan = function(){
console.log(this.name + ' is ' + this.age + ' years old ') //jirengu is 30 years old
}
//使用new操作符进行实例化
var people = new Peoole('aaa',30)
people.slogan()
3、prototype 是什么?有什么特性
- JavaScript的每个对象都继承另一个对象,后者称为“原型”(prototype)对象。只有null除外,它没有自己的原型对象。
- 原型对象上的所有属性和方法,都能被派生对象共享。
- 通过构造函数生成实例对象时,会自动为实例对象分配原型对象。每一个构造函数都有一个prototype 属性,这个属性就是实例对象的原型对象。
- prototype里的属性一旦更改,其实例内也将发生变化
在JavaScript中,所有的对象都是基于 Object;
所有的对象都继承了Object.prototype的属性和方法,它们可以被覆盖(除了以null为原型的对象,如 Object.create(null))。例如,新的构造函数的原型覆盖原来的构造函数的原型,提供它们自己的 toString() 方法.。对象的原型的改变会传播到所有对象上,除非这些属性和方法被其他对原型链更里层的改动所覆盖。
Object.prototype.constructor 用于创建一个对象的原型。
Object.prototype.proto 指向当对象被实例化的时候,用作原型的对象。
4、画出如下代码的原型图
function People (name){
this.name = name;
this.sayName = function(){
console.log('my name is:' + this.name);
}
}
People.prototype.walk = function(){
console.log(this.name + ' is walking');
}
var p1 = new People('aaa');
var p2 = new People('bbb');
原型链相关问题
问题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_ === Person.prototype //ture,p是Person的实例对象,自动获得一个_proto_对象
Preson.prototype.constructor === Person //ture
问题8: 上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。
对象P是没有toString这个方法的,但是它有一个
__proto__
属性是指向Person.prototype,Person.prototype中也没有这个方法就沿着Person.prototype中的__proto__
继续找,到了Object.prototype中就有了toString的方法,就可以调用了。这样沿着__proto__
的“链”就是原型链。
问题9:对String做扩展,实现如下方式获取字符串中频率最高的字符
String.prototype.getMostOften = function(){
var str = {}
var max = 0
var max_key = ''
for(var i = 0; i<this.length ;i++){
var key = this[i]
if(!str[key]){
str[key] = 1
}else{
str[key]++
}
}
for(key in str){
if(str[key]>max){
max = str[key]
max_key = key
}
}
return max_key
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
问题10: instanceOf有什么作用?内部逻辑是如何实现的?
instanceOf用来判断对象是否是另一个的对象的实例,并返回布尔值。
内部逻辑:顺着对象的原型连一直往上找,若原型链上的某一个__proto__
指向了构造函数的prototype则返回true,找完了原型链也找不到则返回false。
Object.prototype.instanceOf = function(obj1,obj2){
var obj1 = obj1.__proto__;
while(obj1.__proto__){
if(obj1 === obj2.prototype){
return true;
}else{
obj1 = obj1.__proto__;
}
return 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);
方法1:是将所有的属性和方法都写在构造函数中,每次新建对象都要创建一个printName函数,会造成很大的内存浪费。
方法2:把printName函数写在原型链上,新建对象可以共享这个方法,节省内存。
问题13: Object.create 有什么作用?兼容性如何?
Object.create() 方法创建一个拥有指定原型和若干个指定属性的对象。Object.create是在ES5中规定的,IE9以下无效。
问题14: hasOwnProperty有什么作用? 如何使用?
hasOwnPerperty是Object.prototype的一个方法,可以判断一个对象是否包含自定义属性而不是原型链上的属性,hasOwnProperty是JavaScript中唯一一个处理属性但是不查找原型链的函数。
用法
obj.hasOwnPerperty('key') // true or 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;
}
调用Person函数,使Male函数能够执行Person上的初始化代码,实现构造函数继承,并且使Person执行时的this指向Male
问题16: 补全代码,实现继承
function Person(name, sex){
this.name = name
this.sex = sex
}
Person.prototype.getName = 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.printName = function(){
console.log(this.name)
}
Male.prototype.getAge = function(){
console.log('age is'+ this.age)
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();