• Javascript-oop-面向对象笔记1


    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>面向对象</title>
    </head>
    <body>
    <script type="text/javascript">
    //JavaScript是一种基于对象的语言,但是又不是真正面向对象编程(oop)语言,因为语法中并没有class类
    //生成一个原型对象
    /*var anminal = {
    name : '',
    age : ''
    }*/
    //根据原型对象,生成实例对象
    /*var cat ={}//生成一个空的对象
    cat.name = '小米';//按照原型对象的属性赋值
    cat.age = 13;
    var monkey = {};
    monkey.name = "小候";
    monkey.age = 14;*/
    //这种是最简单的封装,但是有2个缺点:一是如果多生成几个实例,写起来就非常麻烦;二是实例与原型之间,没有任何办法可以看出有什么联系。
    //写一个函数解决代码重复问题
    /*function anminal(name,age){
    return {
    name : name;
    age : color
    }
    }*/
    //生成实例对象,等于在调用函数
    /*var cat = anminal('小米',13);
    var monkey = anminal('小候',14);*/
    //问题:cat和monkey间没有内在的联系,不能反映出它们是同一个原型对象的实例。为了解决这个问题,javaScript提供了一个构造函数Constructor模式,所谓构造函数其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成出实例,并且this变量会绑定在实例对象上。
    /*function anminal(name,age){
    this.name = name;
    this.age = age;
    }*/
    //生成实例对象
    /*var cat = new anminal('小米',13);
    var monkey = new anminal('小候',14);*/
    //这是cat和monkey自动含有一个constructor属性,并指向它们的构造函数
    //console.log(cat.constructor==anminal);//为true
    //console.log(monkey.constructor==anminal);//为true
    //另外JavaScript还提供了一个叫instanceof运算符,验证原型对象与实例对象之间的关系。
    //console.log(cat instanceof anminal);//为true
    //console.log(monkey instanceof anminal);//为true
    //构造函数虽然好用,但存在浪费内存的问题。例如
    /*function anminal(name,age){
    this.name = name;
    this.age = age;
    this.type = "猴子";
    this.eat = function(){
    alert("吃香蕉");
    return 'SKHDFKLF';
    };
    }*/
    //生成实例
    /*var cat = new anminal('小米',13);
    var monkey = new anminal('小候',14);
    alert(cat.type);
    cat.eat();*/
    //这样写有一个弊端,那就是对于每一个实例对象type属性和eat()方法都是一模一样,每次生成一个实例,都必须为重复的内容多占用一些内存既不环保,更缺乏效率
    //console.log(cat.eat == monkey.eat);//为false,this指向当前
    //那能不能让type属性和eat()方法在内存中只生成一次,然后所有实例都指向那个内存地址javaScript规定,结果肯定是可以的,每一个构造函数都有一个prototype属性指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例及成果,我们可以把那些不变的属性和方法,直接定义在prototype对象上
    /*function anminal(name,age){
    this.name = name;
    this.age = age;
    }
    anminal.prototype.type = "猴子";
    anminal.prototype.eat = function (){
    alert("吃香蕉");
    }
    var cat = new anminal('小米',13);
    var monkey = new anminal('小候',14);*/
    //alert(cat.type);
    //cat.eat();
    //这时所有实例,其实就是同一个内存地址,指向prototype对象,因此就提高了运行效率。
    //console.log(cat.eat == monkey.eat);//true
    //javaScript还为prototype提供了验证方法
    //1.isPrototypeOf():这个方法用来判断,某个proptotype对象和某个实例之间的关系
    //console.log(anminal.prototype.isPrototypeOf(cat));//为true
    //console.log(anminal.prototype.isPrototypeOf(monkey));//为true
    //2.hasOwnProperty():用来判断一个属性到底是本地属性还是继承prototype对象的属性
    //alert(cat.hasOwnProperty("name"));//true
    //alert(cat.hasOwnProperty("eat"));//false
    //alert(cat.hasOwnProperty("type"));//false
    //3.in运算符:用来判断某个实例是否含有某个属性,不管是不是本地属性
    /*alert("name" in cat);//true
    alert("type" in cat);//true
    //in运算符还可以用来遍历某个对象的是所有属性
    for(var anminals in cat){
    alert("cat["+anminals+"]="+cat[anminals]);
    }*/
    //综上所述
    //Javascript的数据和成员封装很简单。没有类完全是对象操作。纯动态
    //Javascript function中的this指针很关键,如果没有的话,那就是局部变量或局部函数。
    //Javascript对象成员函数可以在使用时临时声明,并把一个全局函数直接赋过去就好了。
    //属性配置——Object.defineProperty
    //创建对象
    //var obj = Object.create(null);
    //设置一个属性
    /*Object.defineProperty(
    obj,'name',{ value: 'shu xing',
    writable: true,
    configurable: true,
    enumerable: true
    }
    );*/
    //设置多个属性
    /*Object.defineProperties(obj,
    {
    'age' :{
    value: 11,
    writable: true,
    configurable: true,
    enumerable: true
    },
    'sex' :{
    value: '女',
    writable: true,
    configurable: true,
    enumerable: true
    }
    }
    );*/
    //writable:这个属性的值是否可以改。
    //configurable:这个属性的配置是否可以改。
    //enumerable:这个属性是否能在for…in循环中遍历出来或在Object.keys中列举出来。
    //value:属性值。
    /*var ages = 0;
    Object.defineProperty(obj,
    'ages', {
    get: function() {
    return age+1;
    },
    set: function(value) {
    age = value;
    },
    enumerable : true,
    configurable : true
    }
    );
    obj.ages = 100;*/ //调用set
    //console.log(obj.ages);//调用get输出101(get中加一)
    //综上例子get/set访问器,是用一与get/set来取代value,其不能和value一起使用
    //利用已有的属性(ages)通过get和set构造新的属性
    /*Object.defineProperty(obj,
    'birth_year',
    {
    get: function() {
    var d = new Date();
    var y = d.getFullYear();
    return ( y - this.ages );
    },
    set: function(year) {
    var d = new Date();
    var y = d.getFullYear();
    this.ages = y - year;
    }
    }
    );
    console.log(obj.birth_year);
    obj.birth_year = 2000;
    console.log(obj.ages);*/
    //虽然麻烦,但可以通过defineProperty()可以设置writable,configurable,enumerable等这类的属性配置,还可以动态地为一个对象加属性。比如一些HTML的DOM对象
    //列出对象的属性
    /*function listProperties(obj){
    var newLine = "<br/>";
    var names = Object.getOwnPropertyNames(obj);
    for (var i = 0; i < names.length; i++) {
    var prop = names[i];
    document.write(prop + newLine);
    //列出对象的属性配置(descriptor)动用getOwnPropertyDescriptor函数。
    var descriptor = Object.getOwnPropertyDescriptor(obj,prop);
    for(var attr in descriptor){
    document.write("..." + attr + ': ' + descriptor[attr]);
    document.write(newLine);
    }
    document.write(newLine);
    }
    }
    listProperties(obj);*/
    //查看对象属性配置。上面这个程序可以输出对象的属性和配置等东西,
    /*function print (text){
    document.write(this.value+'---------'+text+'<br/>');
    }
    var a = {
    value : 10,
    print : print
    };
    var b = {
    value : 20,
    print : print
    }*/
    //call和apply函数的差别:参数样子不一样性能不一样,apply的性能要差得多
    /*print.call(a,'a');//10---------a
    print.call(b,'b');//20---------b
    print.apply(a,['a']);//10---------a
    print.apply(b,['b']);//20---------b*/
    //bind,在bind后,this指针,可能会有不一样,因为JavaScript是动态的
    /*var p = print.bind(a);
    p('a');//10---------a
    p.call(b,'b');//10---------b
    p.apply(b,['b']);*///10---------b
    //继承和重载
    //通过上面的例子,我们可以通过Object,create()来实际继承
    var Person = Object.create(null);
    Object.defineProperties(Person,
    {
    'name' : {
    value : 'wei wei'
    },
    'email' : {
    value : '835328162@qq.com'
    },
    'we' : {
    value : 'http://cocdvvcvvcv.cn'
    }
    }
    );
    Person.sayHello = function (){
    var hello = "<p>hello,I am" + this.name +",<br/>"+
    "my email is:" + this.email + ",<br/>" +"my we is:"+this.we;
    document.write(hello+"<br>");
    }
    var Student = Object.create(Person);
    Student.no = "1234567"; //学号
    Student.dept = "Computer Science"; //系
    //使用Person的属性
    //document.write(Student.name + ' ' + Student.email + ' ' + Student.we +'<br>');
    //使用Person的方法
    Student.sayHello();
    //重载sayHello方法
    Student.sayHello = function (person){
    var hello = "<p>Hello, I am "+ this.name + ", <br>" +
    "my email is: " + this.email + ", <br>" +
    "my we is: " + this.we + ", <br>" +
    "my student no is: " + this. no + ", <br>" +
    "my departent is: " + this. dept;
    document.write(hello + '<br>');
    }
    //再次调用
    //Student.sayHello();
    //查看Student的属性(只有no、dept重载了sayHello);
    //document.write('<p>'+Object.keys(Student)+'<br>');
    //通过上面例子 可以做到Person里的属性并没有被真正复制到了Student中,但是我们可以去存取,因为JavaScript用委托实现了这机制这就是Pprototype,Person是Student的Prototype。
    //当我们编写的代码需要一个属性的时候,JavaScript的引擎会先看当前的这个对象中是否有这个属性,如果没有,就会查找它的prototype对相关是否有这个属性,并且一直继续下去,直到找到或没有prototype对象,为了证明,我们可以使用Object.getPrototypeOf()来 进行验证
    Student.name = 'weiwei';
    //document.write('<p>'+Student.name+'</p>');
    //document.write('<p>'+Object.getPrototypeOf(Student).name+'</p>');
    Student.sayHello = function (person){
    Object.getPrototypeOf(this).sayHello.call(this);
    var hello = "my student no is: " + this. no + ", <br>" +
    "my departent is: " + this. dept;
    document.write(hello + '<br>');
    }
    Student.sayHello();
    //你还可以在子对象的函数里调用父对象的函数,就好像C++里的 Base::func() 一样。我们重载hello的方法就可以使用父类的代码
    Student.sayHello = function (person){
    Object.getPrototypeOf(this).sayHello.call(this);
    var hello = "my student no is: " + this. no + ", <br>" +
    "my departent is: " + this. dept;
    document.write(hello + '<br>');
    }
    Student.sayHello();
    //组合
    //首先我们应该定义一个Composition的函数(target是作用于是对象,source是源对象)
    function Composition(target,source){
    var desc = Object.getOwnPropertyDescriptor;
    var prop = Object.getOwnPropertyNames;
    var def_prop = Object.defineProperty;
    prop(source).forEach(
    function(key) {
    def_prop(target, key, desc(source, key))
    }
    )
    return target;
    }
    //就是把source里的属性一个一个拿出来然后定义到target中
    //艺术家
    var Artist = Object.create(null);
    Artist.sing = function() {
    return this.name + ' starts singing...';
    }
    Artist.paint = function() {
    return this.name + ' starts painting...';
    }
    //运动员
    var Sporter = Object.create(null);
    Sporter.run = function() {
    return this.name + ' starts running...';
    }
    Sporter.swim = function() {
    return this.name + ' starts swimming...';
    }
    Composition(Person, Artist);
    document.write(Person.sing() + '<br>');
    document.write(Person.paint() + '<br>');
    Composition(Person, Sporter);
    document.write(Person.run() + '<br>');
    document.write(Person.swim() + '<br>');
    //Person中有?(输出:sayHello,sing,paint,swim,run)
    document.write('<p>' + Object.keys(Person) + '<br>');
    //prototype 继承
    var plus = function(x,y){
    document.write( x + ' + ' + y + ' = ' + (x+y) + '<br>');
    return x + y;
    };
    var minus = function(x,y){
    document.write(x + ' - ' + y + ' = ' + (x-y) + '<br>');
    return x - y;
    };
    var operations = {
    '+': plus,
    '-': minus
    };
    var calculate = function(x, y,operation){
    return operations[operation](x, y);
    };
    calculate(12, 4, '+');
    calculate(24, 3, '-');
    var Cal = function(x,y){
    this.x = x;
    this.y = y;
    }
    Cal.prototype.operations = {
    '+': function(x, y) { return x+y;},
    '-': function(x, y) { return x-y;}
    };
    Cal.prototype.calculate = function(operation){
    return this.operations[operation](this.x, this.y);
    };
    var c = new Cal(4, 5);
    Cal.calculate('+');
    Cal.calculate('-');
    //这就是prototype的用法,prototype 是javascript这个语言中最重要的内容。prototype就是对一对象进行扩展,特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的(这里没有真正的复制,实际只是委托)。上面例子中,我们扩展了实例Cal,让其有了一个operations的属性和一个calculate的方法。
    </script>
    </body>
    </html>

  • 相关阅读:
    一个实用的JS自定义函数addLoadEvent()
    Vim快捷键分类(二)
    Vim快捷键分类(一)
    变量的作用域
    高效整洁CSS代码原则 (上)
    高效整洁CSS代码原则 (下)
    OpenGL 函数作用列表
    glViewport()函数和glOrtho()函数的理解
    车辆动力学基础(1)
    OpenGL: glFlush 和glSwapBuffer
  • 原文地址:https://www.cnblogs.com/835328162qq/p/7741625.html
Copyright © 2020-2023  润新知