什么是JavaScript中的面向对象? 与其他编程语言的面向对象有什么区别? 什么是原型?

 面向对象与原型模式

1.1. js的对象:

定义:是"无序属性的集合,其属性可以包含基本值,对象,和函数",没有类的概念(其他面向对象的语言都有类的概念)
面向对象思维:把解决问题的关注点放在解决问题的所需对象上.

1.2. 面向对象的三大特性:

1.2.1. 封装

就是讲一系列属性和方法,也就是功能 ,封装在对象里面,对象对外界暴露一些接口,外界在使用的时候,不需要关心对象内部的具体功能.

1.2.2. 继承

# 其他面向对象语言中的继承:有父子关系.
# JS中的继承:自己没有的东西,别人有,拿过来用就是继承.
* 例:
 var wangsicong = {};
    var wangjianlin = {
    money:9999,
    manageCompany:function(){
    console.log('我的公司');
    }
};
console.log(wangsicong);

* 混入式继承(mix-in)
for(var k in wangjianlin){
    wangsicong[k] = wangjianlin[k];
}
console.log(wangsicong);


* 原型的继承
    1通过混入的方式为原型新增成员,以实现继承
    2直接替换原型
  var obj1 = {属性与方法};
        function Person(){};        //构造函数
        Person.prototype = obj1;        
        var P1 = Person();


*经典继承 :   Object.create()        //存在兼容问题
  语法:  var 对象1 = Object.create(对象2);        //将对象2作为对象1的原型
    兼容封装:
 function = myCreate(obj){
        if(Object.create){
            return Object.create(obj);
        }else{
            var Create = function(){}
            Create.prototype = obj;
            return new Create();
        }
    }

1.2.3. 多态

多态就是父类指针指向子类对象.
JS中不支持多态

1.3. 创建对象的方式

1.3.1. 1字面量

* 优点:简单易用
* 缺陷:复用性比较差
var  obj = {
    name:'小红',
    sayHi:function(){
        consol.log('我爱吃');
    }
}

1.3.2. 2使用内置构造函数object

* 缺陷:1创建出的是空对象;        2复用性差
var obj = new object();

1.3.3. 3自定义构造函数

例:
 function Person(形参){
    this.name = 形参,
    this.sarHi = function(){
        console.log('你好');
    }
}
var p1 = new Person(实参);
var p2 = new Person(实参);
console.log(p1.sarHi == p2.sarHi);    //false    不在同一个地址,但用的相同的方法
# 什么是构造函数??    
构造函数一般是用来初始化对象的函数(不是创建对象:是new创建的)!
# 构造函数的特点:
    * 首字母大写(规范)
    * 一般和new关键字一起使用
    * 不需要手动写返回语句,会默认返回新创建出来的对象.

# 构造函数执行的过程:
    * 使用new关键字构造函数
    * 调用构造函数
    * 将构造函数内部的this指针指向创建出的对象
    * 使用this指针在构造函数内部对对象进行初始化操作(新增成员)
    * 默认的将创建出来的对象返回

# 构造函数使用注意事项:
    * 如果没return,返回的是构造出的对象
    * 如果手动返回的是值类型的数据,不会对默认返回值有任何影响
    * 如果手动返回的是引用类型的数据,使用new关键字创建的对象被抛弃 
    * 将构造函数当做普通函数调用的时候,this指向window,如果返回值不写,返回undefined


## 传统构造函数存在的问题:
    # 问题每次进来都创建相同的方法,造成资源浪费!
    * 解决:将函数声明放在构造函数外面,将构造函数的地址赋值给对象的方法.
    * 这样解决的问题:
        1全局变量污染
        2代码结构混乱,不利于维护
        3不安全 ,容易被人更改
    * 解决方案:原型    

1.4. 原型模式

1.4.1. 原型?:在构造函数创建出来的时候系统会默认的帮构造函数创建且关联一个空对象,这个对象就是原型

1.4.2. 原型的作用?

在原型中的所有属性和方法,都可以被其关联的构造函数创建出来的对象所共享(与其他编程语言中的类可以相对应理解,但不相同)

1.4.3. 如何访问原型?

  1 构造函数.prototype;
  2 对象.__proto属性__(两个下划线)
* 非标准属性:ECMA中没有的属性,不推荐使用,只适合在调试过程中使用!(一般两个下划线开头的属性都是非标准的属性,单下划线开头的是私有属性)
* 例:
  function Obj(){}
    var man = new Obj();
    console.log(Obj.prototype === man.__proto__);    //true

1.4.4. 原型的使用?

例1使用动态特性:        添加的成员少的时候
function Obj(){}
Obj.prototype.sayHi = function(){
    console.log('我是原型中的sayHi');
};
var p1 = new Obj(); 
var p2 = new Obj();
console.log(p1.sayHi() == p2.sayHi())   //true


 例2:替换原型:        添加的成员多的时候
Obj.prototype = {
    属性,
    sayHi:function(){
    console.log('我是原型中的sayHi');
    }
var p1 = new Obj();
var p2 = new Obj();

1.4.5. 原型使用注意事项:

*对象只有访问不到本身属性的时候才会去原型中查找.设置属性不会去原型中查找
*一般情况下,只会将方法放在原型中,属性放在对象中(方法是一样的,每个对象的属性是不一样的)
*需要将原型放在上面,否则有可能访问不到
*替换原型的时候,替换之前的原型与替换之后的原型不一致
*对象的原型,就是创建对象的那一刻,构造函数所关联的原型

1.4.6. 实例化:通过构造函数实例化一个对象,(也就是所谓的创建对象)

1.4.7. 原型链:

js中所有的对象都有原型,原型也有对象,所以原型对象也有原型.
# 构造函数.prototype的成员介绍:
    * constructor属性,从原型指向关联的构造函数(原型的属性)
        console.log(Obj.prototype.constructor);
    * 对象.hasOwnProperty(属性);            //判断对象有没有这个属性
    * 当前对象.isPrototypeOf(另一个对象);      //判断当前对象是不是另一个对象的原型
    * obj.propertyIsEnumerable(属性);        //判断属性是否属于此对象并且可以被遍历
    * __proto属性__
    * toString()    与     toLocaleString()
        都是将对象转换成字符串的方法
        但是toLocaleString()会将对象转换成本地格式的字符串
    * valueOf()
        获取属性得值    
        当引用类型与值类型的数据参与运算的时候会调用valueOf,如果不能运算再调用toString()
 # 对象 instanceof 构造函数
    判断此构造函数的原型有没有在此对象的原型链上 

原型链实例:
  下面是建立了一个preson对象:
  
  function Preson(){}
  var preson = new Preson();

  这是一条preson对象的完整的原型链:

  

1.4.8. 属性搜索原则:

*1当使用属性访问成员的时候,会先在对象自身查找
*2如果没有找到,就去对象的原型中查找
*3如果没有找到,就沿着原型链继续往上查找,直到null

1.5. 如何安全的扩展内置对象?

// 例1:避免这么做!!
var arr = new Array();    //array构造函数
    Array.prototype.max = function(){
    return 1;
}
arr.max();
//应当避免对内置对象进行直接修改,会影响别人代码!!
 
// 例2:应当这么做!!
function MyArray(){}
MyArray.prototype = [];
MyArray.prototype.max = function(){
    return 1;
}
var myarr = new MyArray();
arr.max();
//MyArray继承了数组的原型并进行扩展,并不会修改内置数组对象的原型
 
原文地址:https://www.cnblogs.com/canday/p/6204779.html