JS高级学习总结--面向对象

一、对象的四种创建方式

1)直接量

var Student = {name:'小明',age:18};

  2)通过new关键字加Object()构造函数

var student = new Object()
student.id = 10;
student.name = '王铁锤';
student.age = 18;    

缺点:使用同一个接口创建很多对象,会产生大量的重复代码.

  3)封装工厂函数

  为了减少重复代码,对上述代码进行封装

  4)自定义构造函数

/*
*   这种方式调用构造函数实际上会经历以下4个步骤:
*   1> 创建一个新对象;
*    2> 将构造函数的作用域赋给新对象(把this绑定到实例对象);
*    3> 执行构造函数中的代码(为这个新对象添加属性);
*    4> 返回新对象。 
*/
function Student(name, age){
this.name = name;
this.age = age;
this.sayName = function(){alert(this.name);};
}
var s1 = new Student("王铁锤", 18);

  构造函数与普通函数的唯一区别(调用方式不同):

  1>任何函数,只要通过new操作符来调用,它就可以作为构造函数;
  2>而任何构造函数,如果不通过new 操作符来调用,那它跟普通函数无区别。
  约定:构造函数首字母大写
  缺点: 构造函数方法很好用,但是存在一个浪费内存的问题。这样既不环保,也缺乏效率。 

 二、this关键字
     this作为JS的关键字,有特殊的含义,代表了当前对象,而当前对象是谁,由函数执行时所处的环境来决定
     1>用new关键字执行:this指向生成的实例对象
     2>普通函数执行:this指向调用函数的对象

 三、构造函数、实例、与原型对象的关系

  

  原型对象:prototype
                1> 我们创建的每个函数都有一个prototype属性,这个属性值就是原型对象
                2> 原型对象默认包含一个constructor属性,指向构造函数
                3> 任何写在原型对象中的属性和方法都可以让所有对象实例共享

     实例:
                当调用构造函数创建一个新实例后,该实例的内部将包含一个内部属性[[Prototype]],指向构造函数的原型对象。这个内部属性无法直接访问,在FF,Chrome等浏览器可以通过__proto__得到;或者通过ES5方式Object.getPrototypeOf(实例)去获取


     构造函数、原型对象和实例的关系:
                1>每个构造函数都有一个原型对象(prototype),
                2>原型对象都包含一个指向构造函数的指针(constructor),
                3>而实例都包含一个指向原型对象的内部指针([[prototype]])

     判断原型和实例的关系(返回布尔值)
               constructor: 得到构造函数的引用,一般用于判断该实例是否由某一构造函数生成
               实例.constructor == Student //true
               instanceof: 检测某个对象是不是某一构造函数的实例,适用于原型链中的所有实例
               实例 instanceof Student //true
               实例 instanceof Object //true
               isPrototypeOf: 判断当前对象是否为实例的原型
               原型对象.isPrototypeOf(实例) //true

  原型链
            原型链:实例与原型对象的链条
            原型搜索机制扩展
                最后搜索到Object构造函数

  四、对象对属性的访问过程

  实例对象属性的读取和写入
            1)读取(原型搜索机制):
                当代码读取对象的某个属性时,会先从对象实例本身开始搜索。如果在实例中找到了这个属性,则返回该属性的值;如果没有找到,则继续搜索原型对象,如果在原型对象中找到       了这个属性,则返回该属性的值

            2)写入:
                虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。如果我们在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,该属性将会       屏蔽原型中的那个属性。(一句话:添加属性/方法只会在对象实例中添加)

            3)对象属性的遍历与判断
                1> for…in:遍历对象中的所有属性, 无论该属性存在于实例中还是原型中
                2> in:只要通过对象能够访问到属性就返回true, 无论该属性存在于实例中还是原型中
                    if(name in s1){}
                3>实例.hasOwnProperty(属性):检测一个属性是存在于实例中(true),还是存在于原型中(false)
                4>检测一个属性是否存在于原型中:!obj.hasOwnProperty(name) && (name in obj)

  

  五、面向对象的继承

  借用构造函数
                call:使用父类函数的call(子类对象,参数1,参数2,参数3......) 最常见
                    格式:构造函数.call(this,参数1,参数2,参数3......)
                apply:使用父类函数的apply(子类对象,[参数1,参数2,参数3])
                    格式:父类构造函数.apply(子类当前对象,[参数1,参数2,参数3......])//第二个参数为数组
                **call与apply的唯一区别:传参方式不同
                **借用构造函数法只能继承构造函数里的属性/方法,不能继承原型对象里的方法
                PS:借用构造函数法一般用于继承属性

  原型式继承
                function object(o){
                    function F(){}
                    F.prototype = o;
                    return new F();
                }
                原理:先创建了一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回了这个临时类型的一个新实例
                Object.create():ECMAScript 5版本的原型式继承

  寄生组合继承法
                继承属性:借用构造函数
                继承方法:原型式继承

原文地址:https://www.cnblogs.com/hackerPJ/p/5655283.html