前端面试题必考(六)- JS快速复习(面向对象/常用封装写法/闭包/继承)

没时间了,这里只记我所知道的重点知识

一.描述面向对象/特点

1.面向对象由属性和方法组成,并有三个基本特征:

  • 封装:只能通过对象来访问方法;
  • 继承:从已有对象上继承出新的对象;JS不支持接口继承,实现继承的方式依靠原型链完成。
  • 多态:多对象的不同形态;允许将子类类型的指针赋值给父类类型的指针。实现多态,有二种方式:覆盖,重载,接口

*删除对象:JavaScript自己垃圾回收机制,就是自己在没有引用的时候释放内存(销毁)

var obj=new Object();
obj.name="haha";
alert(obj);//{name:"haha"}
//obj=null;
//obj={};
obj=new Object();
alert(obj);//{}

*删除对象属性:

var obj={name:"haha"};
delete obj.name;
alert(obj.name);//undefined

二.原型封装(js面向对象的几种常见写法,参考:https://www.cnblogs.com/leejersey/p/4205252.html,http://www.cnblogs.com/jnslove/p/7028487.html

1>工厂模式

var Circle = function() {
   var obj = new Object();
   obj.PI = 3.14159;
   
   obj.area = function( r ) {
       return this.PI * r * r;
   }
   return obj;
}

var c = new Circle();
alert( c.area( 1.0 ) );

2>构造函数模式,与工厂模式的区别:没有显式的创建对象;直接将属性和方法赋给this对象;没有return语句

function CreatePerson(name){
    
    this.name = name;
    this.showName = function(){
        alert( this.name );
    };
}
var p1 = new CreatePerson('小明');
//p1.showName();
var p2 = new CreatePerson('小强');
//p2.showName();
alert( p1.showName == p2.showName );  //false  它们的值相同,地址不同

3>原型模式:原型(prototype),重写对象下面公用的属性或方法,让公用的属性或方法在内存中只存在一份(提高性能),也就是说所有在原型对象中创建的属性或方法都直接被所有对象实例共享。原型:类比css中的class;普通方法:类比css中的style

var arr = [1,2,3,4,5];
var arr2 = [2,2,2,2,2];
Array.prototype.sum = function(){//原型prototype : 要写在构造函数的下面
    var result = 0;
    for(var i=0;i

注意:原型优先级,如果在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,该属性将会屏蔽原型中的那个属性

例1:

var arr = [];
arr.number = 10;
Array.prototype.number = 20;
alert(arr.number);//10

例2:

Array.prototype.a=12;//原型属性
var arr=[1,2,3];
alert(arr.a);//12
arr.a=5;//实例属性
alert(arr.a);//5

3>工厂方式之原型

例1:

function Circle(r) {
      this.r = r;
}
Circle.PI = 3.14159;
Circle.prototype.area = function() {
  return Circle.PI * this.r * this.r;
}

var c = new Circle(1.0);   
alert(c.area()); 

例2:

var Circle=function(r){
        this.r=r;
}
Circle.PI = 3.14159; 
Circle.prototype={
    area:function(){
        return this.r*this.r*Circle.PI;
    }
}
var obj=new Circle(1.0);
alert(obj.area())

例3:

function CreatePerson(name){//普通方法
this.name=name;
}
CreatePerson.prototype.showName=function(){//原型
alert(this.name);
}
var p1=new CreatePerson('小明');
p1.showName();
var p2=new CreatePerson('小强');
p2.showName();
alert( p1.showName== p2.showName);//true  

 

4>JSON写法

var Circle={
   "PI":3.14159,
 "area":function(r){
          return this.PI * r * r;
        }
};
alert( Circle.area(1.0) );

5>JSON写法的扩展小实例

var show={
        btn:$('.div1'),
        init:function(){
            var that=this;
            alert(this);
            this.btn.click(function(){
                    that.change();
                    alert(this);
                })
            
        },
        change:function(){
            this.btn.css({'background':'green'});

        }
}
show.init();

三.闭包(参考:https://www.cnblogs.com/yunfeifei/p/4019504.html)

Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

上述原型的例子写法都属于闭包,除此之外还有一种常见写法:

var Circle = new Function(
this.PI = 3.14159;
this.area = function( r ) {return r*r*this.PI;}
);  
alert( (new Circle()).area(1.0) );  

四.继承(参考:https://www.cnblogs.com/jingwhale/p/4678656.html

  • 在现代浏览器中可以使用 Object.create 实现继承。
  • ECMAScript 只支持继承,不支持接口实现,而实现继承的方式依靠原型链完成。

1.call+遍历

属性使用对象冒充(call)(实质上是改变了this指针的指向)继承基类,方法用遍历基类原型。可以实现多继承。

function A(){
    this.abc=12;
}
A.prototype.show=function (){
    alert(this.abc);
};
//继承A
function B(){
    //继承属性;this->new B()
    A.call(this);   //有参数可以传参数A.call(this,name,age)
}
//继承方法;B.prototype=A.prototype;
for(var i in A.prototype){
    B.prototype[i]=A.prototype[i];
}
//添加自己的方法
B.prototype.fn=function (){
    alert('abc');
};
var objB=new B();
var objA=new A();
objB.show();

2.寄生组合继承主要是Desk.prototype = new Box(); Desk 继承了Box,通过原型,形成链条。主要通过临时中转函数和寄生函数实现。

  • 临时中转函数:基于已有的对象创建新对象,同时还不必因此创建自定义类型
  • 寄生函数:目的是为了封装创建对象的过程
//临时中转函数 
function obj(o) { //o表示将要传递进入的一个对象 
    function F() {} //F构造是一个临时新建的对象,用来存储传递过来的对象 
    F.prototype = o; //将o对象实例赋值给F构造的原型对象 
    return new F(); //最后返回这个得到传递过来对象的对象实例 
} 
//寄生函数 
function create(box, desk) { 
    var f = obj(box.prototype); 
    f.constructor = desk; //调整原型构造指针 
    desk.prototype = f; 
} 
function Box(name) { 
    this.name = name; 
    this.arr = ['apple','pear','orange']; 
} 
Box.prototype.run = function () { return this.name; }; 
function Desk(name, age) { 
    Box.call(this, name); 
    this.age = age; 
} 
//通过寄生组合继承实现继承 
create(Box, Desk); 
//这句话用来替代Desk.prototype = new Box(); 
var desk = new Desk('Lee',100); 
desk.arr.push('peach'); 
alert(desk.arr); 
alert(desk.run());

临时中转函数和寄生函数主要做的工作流程:

  • 临时中转函数:返回的是基类的实例对象函数
  • 寄生函数:将返回的基类的实例对象函数的constructor指向派生类,派生类的prototype指向基类的实例对象函数(是一个函数原型),从而实现继承。

 

 

-------------------------------<本节完>------------------------------------------

 

 

你可能感兴趣的:(前端面试题必考(六)- JS快速复习(面向对象/常用封装写法/闭包/继承))