2017-03-27 面向对象预习

2017-03-27  本文已影响0人  GodlinE

原型对象补充

继承的实现

function Person(){
        this.name = '默认的名称';
        this.friends = ['123','456','789'];
}
Person.prototype.hi = 'hi';
var p1 = new Person();
var o = {};
//拷贝属性
for(var k in p1){
        if(p1.hasOwnProperty(k)){
                  o[k] = p1[k]
        }
}
console.log(o);
console.log(p1);
o.name = '我是一个数字';
console.log(p1.name);
p1.friends.push('我是测试的狮子')
console.log(o.friends);
console.log(o.hi);
var obj = {
        name:"杂货",
        friends:['二货','硬货','水货'];
}
var obj2 = obj;
obj.name = '散货';
console.log(obj2.name);
obj.friends.push('傻货');
console.log(obj2.friends);
obj.friends = ['123','456','789'];
console.log(obj2.friends,'++++++');
var o1 = {
        arr:['123','234'];
}
var o2 = o1;
console.log(o1.arr == o2.arr);
o1.arr.push('demo');
console.log(o2.arr);
o1.arr= ['demo1','demo2'];
console.log(o2.arr,'+++');
var demo01 = {
        show:function(){
                console.log('show');
        }
}
var demo0 = {};
for(var k in demo01){
        demo02[k] = demo01[k];
}
console.log(demo01.show == demo02.show);
demo01.show = function(){
        console.log('啦啦啦');
}
demo02.show();   //show

继承的实现(原型式继承)

function Person(name){
        this.name = name;
}
Person.prototype.des = '描述信息';
var p1 = new Person('张三');
function Person(name){
        this.name = name;
}
Person.prototype = {
        constructor:Person,
        des:"默认的描述信息",
        var p1 = new Person('张三');      
}
function Person(name){
        this.name = '张三';
}
Person.prototype = {
        constructor:Person,
        des:'默认的描述信息',
        showDes:function(){
                console.log(this.des);
        }
}
//设置构造函数的原型对象为父构造函数的原型对象
Boy.prototype = Person.prototype;
var boy1 = new Boy();
console.log(boy1.des);
boy1.showDes();
boy1.lol();

扩展内置对象

把需要共享的属性和方法写在内置构造函数的原型对象上

var arr1 = [1,2,3];
console.log(arr1);  //arr1的构造函数 Array
console.log(arr1.constructor);
arr1.name = 'arr1的名称';
arr1.desLog = function(){
        console.log('arr1的des');
}
console.log(arr1);
//需求:要求给 arr2 添加属性 name|desLog
var arr2 = ['demo01','demo02'];
arr2.name = 'arr2的名称';
arr2.desLog = function(){
          console.log('arr2的des');
}
console.log(arr2);

需求:要求所有的数组都拥有 name 和 desLog 方法

Array.prototype.name = 'name';
var arr1 = [1,2,3,4,5];
for(var i = 0 ; i < arr1.length:i++){
        console.log(i,arr1[i]);
}
console.log('______');
for(var i in arr1){
        console.log(i,arr1[i]);
}

安全的扩展内置对象

//提供一个自定义的构造函数 (MyArray)
function MyArray(){}
//设置该构造函数的原型对象为内置构造函数的一个实例
        MyArray.prototype = new Array();  //获得 Array 的所有属性和方法
// MyArray.prototype = Array.prototype;
//设置原型对象
        MyArray.prototy[e.name = '默认的名称';
        MyArray.prototype.desLog = function(){
                console.log('哈哈哈哈');
        }
//使用自定义的构造函数来创建对象并且使用
        var myArr01 = new MyArray();
        myArr01.push('123','345');
        console.log(myArr01);
        console.log(myArr01.name);
        myArr01.desLog();
        var myArr02 = new MyArray();
//其他开发人员
function OtherArray(){};
OtherArray.prototype = new Array();
//OtherArray.prototype = Array.prototype;
OtherArray.prototype.name = '默认的名称+++++++';
OtherArray.prototype.desLog = function(){
        console.log('嘿嘿嘿嘿');
}
var other01 = new OtherArray();
other01.push('demo1','demo2');
console.log(other01);
console.log(other01.name);
var arr = new MyArray();
console.log(arr.name);

原型链的结构

function Person(){}
var p1 = new Person();
// p1 是一个对象,因此有构造函数(person)
//构造函数都有原型对象因此 Person.prototype 存在(Object)
//Person.prototype 本身是一个对象(Object),因此也有构造函数(Object)
//Object 的构造函数也有原型对象, Object.prototype
//Object.prototype 本身也是一个对象,这个对象是 Object 类型
//Object.prototype 也有构造函数,构造函数是 Object

原型链中属性的搜索规则

function Person(){
        this.name = 'Person-name';
        this.age = 20;
}
Person.prototype.showName = function(){
        console.log(this.name);
}
function Boy(){
//this.name = 'Boy-name';
}
Boy.prototype = new Person();
Boy.prototype.name = '哈哈';
var boy1 = new Boy();
console.log(boy1.name); // Boy-name
console.log(boye1.age);  //undefined
boy1.showName();  //Boy-name
var p1 = new Person();
console.log(p1.name);

原型链的继承

function A(){
        this.a = 'a';
}
A.prototype.showA = function(){
        console.log('a'); 
}
function B(){
        this.b = 'b';
}
//要求 B 的实例对象拥有 A 构造函数原型对象上面的成员 + 实例对象上面的成员
B.prototype = new A();
var b1 = new B();
console.log(b1.a);
b1.showA();
//b1.constructor

复杂的原型链示例

function Animal(){
        this.color = '红色';
}
Animal.prototype.run = function(){
        console.log('run');
}
function Person(){
        this.name = '人';
}
Person.prototype = new Animal();
Person.prototype.constructor = Person;
Person.prototype.eat = function(){
        console.log('吃饭');
}
function Stydent(){
        this.className = '超神班';
}
Student.prototype = new Person();
//Student.prototype.constructot = Student;
//Student.prototype/read = function(){console.log('阅读');}

//以下是错误演示
//Student.prototype = {
//        constructor:Student,
   //     read:function(){
//                  "读书"
 //       }
//}
function Boy(){
          this.girlF = '林志玲';
}   
Boy.prototype = new Student();
Boy.prototype.constructor = Boy;
Boy.prototype.play = function(){
        console.log('打游戏');
}   
var boy = new Boy();
console.log(boy);
boy.eat();

原型链继承的问题

function Person(name){
        this.name = name;
        this.friends = ['巴拉巴拉','哗啦哗啦','嘀嗒嘀嗒'];
}
Person.prototype.showName = function(){
        console.log(this.name);
}
function Boy(){}
Boy.prototype = new Person('张三');//设置实现原型链继承
var boy1 = new Boy();
console.log(boye1.friends);
var boy2 = new Boy();
console.log(boye2.friends);
boy1.friends.push('呜啦呜啦');
console.log(boy.friends);
console.log(boy2.friends);
console.log(boy1.name);
console.log(boy2.name);

Object.create()方法

var obj = {
          name:"张三",
          showNmae:function(){
                  console.log(this.name);
          }
}
var o = Object.create(obj);
//var o = {}
// o.__proto__ = obj;
console.log(o);
console.log(o.name);
o.showName

兼容处理
先判断是否支持 Object.create,如果不支持那么我们就利用对象的动态特性来自己提供一个方法

var obj = {
        name:"张三",
        showName:funciton(){
                console.log(this.name);
        }
};
var o ;
if(typeof Object.create == 'function'){
        o = Object.creat(obj);
}else{
        //o = {};
        //o.__proto__ = obj; //非标准的属性
        // Object.getPrototypeOf(o) = obj;
        Object.create = function(){
                function F(){};
                F.prototype = obj;
                o = new F();
        }
}

提供一个函数来封装这个功能,在函数内部先判断是否支持 Object.create,如果支持那么就使用 Object.create,否则我们就自己实现

var obj = {
        name:"张三",
        showName:function(){
                console.log(this.name);
        }
}
function creat(objT){
          if(typeof Object.create == 'function'){
                  return Object.create(objT);
          }else{
                  funtion F(){};
                  F.prototype = objT;
                  return new F();
          }
}
//调用函数
var o = creat(obj);

思考

Object.assign()方法

使用 for .. in 遍历拷贝对象的时候,会联通该对象的原型成员一起拷贝

<script>
    var o = {
        name:"张三"
    }
    var o2 = {
        age:20
    }


    var obj = {};
    for(var i in o)
    {
        obj[i] = o[i];
    }
</script>
<script>
    var o = {};
    Object.assign(o, {name:"张三"},{age:20},{showName:function () {
        console.log("name");
    }})

    console.log(o);
    o.showName();

    function F() {}
    F.prototype.hi = "hi";
    var f = new F();
    var obj = {};
    for (var i in f)
    {
        if(f.hasOwnProperty(i))
        {
            obj[i] = f[i];
        }
    }
    console.log(obj.hi);

    var demo = {};
    Object.assign(demo,f);
    console.log(demo.hi);
</script>

call 和 apply 函数

var p1 = {
        name:"张三",
        showName:function () {
            console.log(this.name);
        },
        showDes:function (str1,str2) {
            console.log("des" + str1,str2);
        }
    }
    var p2 = {
        name:"李四"
    }

    p1.showName();   //张三
    p1.showName.call(p2);   //p2借用p1对象的showName方法
    p1.showName.apply();   //window.name = 空("")

    //注意call和apply传递参数的区别
    p1.showDes.call(p2, "啦啦啦啦,暗黑魔法咒语","伏地魔");
    p1.showDes.apply(p2,["啦啦啦啦,暗黑魔法咒语","哈利波特"]);

    function demo(str1,str2,str3) {
    }

    console.log(demo.length);
    console.log(p1.showDes.call.length);
    console.log(p1.showDes.apply.length);

借用构造函数继承的基本写法

 function Person(name,age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.showName = function () {
        console.log(this.name);
    }

    function Boy(name,age) {
        //构造函数内部会默认创建空对象并赋值给this
        Person.call(this,name,age);  //this.name = name;  借用构造函数
    }

    var boy1 = new Boy("张三",20);
    var boy2 = new Boy("李四",30);
    console.log(boy1);
    console.log(boy2);
    boy1.showName();

组合继承写法

function Person(name,age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.showName = function () {
        console.log(this.name);
    }

    function Boy(name,age) {
        //构造函数内部会默认创建空对象并赋值给this
        Person.call(this,name,age);  //this.name = name;  借用构造函数
    }

    //原型链继承
    //Boy.prototype = new Person();  //原型链继承
    Boy.prototype = Person.prototype;    //原型式继承C

    var boy1 = new Boy("张三",20);
    var boy2 = new Boy("李四",30);
    console.log(boy1);
    console.log(boy2);
    boy1.showName();

深拷贝和浅拷贝

var person = {
        name:"张三",
        car:{
            type:"飞船",
            color:"黑色",
            des:{
                number:666888
            }
        },
        arr:[1,2,3,4]
    }


//    var p = {};
//    for(var i in person)
//    {
//        p[i] = person[i];
//        console.log("____");  //0x11
//    }

    //参数1:目标对象 ,参数2:要拷贝属性的对象
    function deepCopy(obj1,obj2) {
        obj1 = obj1 || {};  //容错性处理
        for(var i in obj2)
        {
            //只拷贝实例属性
            if (obj2.hasOwnProperty(i))
            {
                if (typeof obj2[i] == "object")
                {
                    //引用类型,新创建对象,再次遍历
                    //需要判断是数组还是对象
                    obj1[i] = Array.isArray(obj2[i])?[]:{};
                    deepCopy(obj1[i],obj2[i]);
                }else
                {
                    obj1[i] = obj2[i];
                }
            }

        }
    }

    var p = {};
    deepCopy(p, person);
    console.log(p);

    //验证共享的问题是否解决
    person.car.type = "银河战舰";
    console.log(p.car.type);

    console.log(person);

通过深拷贝实现继承

 function deepCopy(obj1,obj2) {
        obj1 = obj1 || {};  //容错性处理
        for(var i in obj2)
        {
            //只拷贝实例属性
            if (obj2.hasOwnProperty(i))
            {
                if (typeof obj2[i] == "object")
                {
                    //引用类型,新创建对象,再次遍历
                    //需要判断是数组还是对象
                    obj1[i] = Array.isArray(obj2[i])?[]:{};
                    deepCopy(obj1[i],obj2[i]);
                }else
                {
                    obj1[i] = obj2[i];
                }
            }

        }
    }

    function Person(name,age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.showName = function () {
        console.log(this.name);
    }

    Person.prototype.hi = "hi";

    function Boy(name,age) {
        //构造函数内部会默认创建空对象并赋值给this
        Person.call(this,name,age);  //this.name = name;  借用构造函数
    }


    deepCopy(Boy.prototype,Person.prototype);

    var boy1 = new Boy("张三",20);
    var boy2 = new Boy("李四",30);
    console.log(boy1);
    console.log(boy2);
    boy1.showName();
    console.log(boy1.hi);
    Boy.prototype.hi = "hahahahah";
    console.log(boy1.hi);

    var p1 = new Person();
    console.log(p1.hi);
上一篇 下一篇

猜你喜欢

热点阅读