javascripts面向对象基础

作者: Dabao123 | 来源:发表于2017-09-19 22:26 被阅读24次

    js中对象的分类

    对象的分类:

    1.内置对象:由ECMA实现 的,不依赖于宿主环境的对象,这些对象在js程序执行之前就已经存在了。
    本地对象:Object,Array,String,Number,Boolean,Date等。
    单体内置对象:只有两个Global,Math。与本地对象的区别在于:不需要加new 。
    2.宿主对象:就是js寄宿环境定义的对象。
    在浏览器端的js而言,宿主对象就是浏览器对象。例如:window,document,history等。
    Global对象:定义的全局变量,全局函数,其实就是这个对象的属性。
    其它的本地对象其实也是它的属性。从这个意义上讲,Global东西相当于是js程序运行总管。
    3.自定义的对象

    window对象

    window是Global对象在浏览器端的代言人。换句话说,在浏览器端编写js程序,就直接可以使用window来代替global。(如果你在你服务器端,在node.js中global对象是真实存在的)。
    定义的任何全局变量,函数,都是window对象的属性。

    var  a = 1,
         b = 2;
    console.log(window.a)  //1
    console.log(window.b)  //2
    

    但是在使用中window可以省略。

    js的三条定律

    一切都是对象
    1.基本数据类型也当作对象处理
    var  string = 'dabao';
    console.log(string.length);
    

    string为基本数据类型,但是他同样有方法,在运行过程中js会把它临时转变成一个包装类的对象。

    var string = new String('dabao')
    
    2.引用类型的数据也是对象

    函数:

    function  f(){}
    console.log(f);
    console.log(f instanceof  Object)  //true
    
    Paste_Image.png

    数组:
    给数组添加新属性,一定要按下标的序号规则去加,如果下标是字符串(正确的下标应该是数字),则length的值不会增加,但,添加的属性确定是添加成功。

    var a = [1,2,3];
    a.name = 'dabao';
    a[3] = 'xiaobao';
    
    Paste_Image.png

    对象自然也是对象。

    属性操作

    四个特征:
    configurable:是否可以删除。默认为true。
    writable:是否可以修改属性的值。默认为true。
    enumerable:是否可以枚举。是否可以通过for in 循环来输出。默认为true。
    Value:值。默认为undefined。

    Object.defineProperty(对象名,“属性名”,{
    Configurable:
    Writable:
    Enumerable:
    Value:
    })

    var obj = {}
    Object.defineProperty(obj,"name",{
            configurable:false,
            writable:false,
            value:'dabao'
    })
    console.log(obj)
    obj.name = 'xiaobao';
    console.log(obj.name)
    delete obj.name;
    console.log(obj);
    
    Paste_Image.png
    函数被调用次数的例子
    function f(){
        f.counter++;
    }
    f.counter = 0;
    f();
    f();
    f();
    console.log(f.counter)   //3
    

    深入理解var 与不加var 的区别

    a = 1;
    console.log(a);  //1
    var b = 2;
    console.log(b);  //2
    delete a;
    delete b;
    console.log(window.a);    //undefined
    console.log(window.b);   //2
    

    遗漏声明变量就是window对象的属性,是可以被删除的。而加var声明是不可删除的。为什么呢?因为使用var添加的属性有一个特性是:configurable:true;

    对象是由函数创造
    var array = new Array(1,1)
    var f = new Function('x','y','return x+y');
    var n = new Number(1)
    var obj = new Object();
    

    无论是数组还是函数还是基本数据类型都是由函数创建的。

    原型与原型链

    prototype就是原型,__ proto__ 称为隐式原型。前后有两个下划线。它对外是隐藏的,我们在程序开发过程,不会直接使用它。
    1.函数都有一个prototype属性
    每个函数,都会有很多属性(因为函数也是对象,而对象是属性的集合),其中一定有一个prototype属性。
    函数的prototype属性是一个对象,这个对象中有很多方法。但是一定有一个方法:constructor,constructor指向 这个函数本身。
    (在es6的语法中,使用class创建类,实际上每个类都有一个constructor,即使你不设置,也会默认存在)
    2.每一个对象都有一个__ proto__属性
    对于函数而言,也是对象,所以函数都会有一个prototype和一个__ proto__属性。
    对象的__ proto__属性指向创建这个对象的函数的prototype。

    function F(){
        this.name = 'dabao'
    }
    var f = new F();
    console.log(F.prototype)
    console.log(f.__ proto__)
    
    Paste_Image.png

    如果访问一个对象的属性时,先在这个对象自己的属性中去找,如果找不到,则沿着__ proto__这个属性找,如果__ proto__这个对象中还是没有找到,就在__ proto__对象的__ proto__属性中去找,依次下去,这就是原型链。
    也就是说,当我们访问对象,会寻找自己的属性,当找不到自己的属性时,就去找自己的隐式原型__ proto__,__ proto__指向创建该对象方法的prototype,prototype实际上也是一个对象,它也有一个__ proto__这样会继续往上一级找。
    由于对象的__ proto__[隐式原型]与创建这个对象的函数(构造器)的prototype是一致的。
    所以理论上,你对__ proto__修改会直接影响prototype。
    建议你只使用prototype[原型]

    创建对象
    字面量方法
    var  obj = {
          name : 'dabao',
          say : function(){
                    console.log(this.name)
          }
    }
    

    工厂模式

    function creatObj(){
             var  obj = {}
             obj.name = 'dabao';
             obj.say = function(){
                     console.log(this.name)   
             }
             return obj;
    }
    
    构造器模式
    function F(){
              this.name = 'dabao'
    }
    var f = new F()
    

    到底做了什么? 为什么给一个函数加一个new 就能产生对象呢?
    new一共做了如下四件事:
    1.创建一个对象 var obj = {}
    2.F.call(obj);先执行F()函数,同时把this用obj来代替。把F()构造器设置的各种属性值,直接赋给o.
    3.obj.__ proto__ = F.prototype
    4.返回 obj;

    原型模式
    function F(){
        this.name = 'cxh'
    }
    F.prototpe.say = function(){}
    

    将方法写在原型上。
    注意:不要去修改对象的__ proto__。会导致由构造器所产生的全部的对象的属性都会受到影响。
    覆盖prototype的问题:
    因为prototype里面肯定有一个contructor方法,假如采用直接覆盖的方法,将把当前的对象的构造器归置为object。
    我们可以采用jq的方法

    Paste_Image.png

    重新设置 constructor。

    继承

    js特点:生来继承
    Var s ={};
    s.toString();//为什么有toString()?从__ proto__获取的。
    1.原型继承

    function Parent(){}
    function Son(){}
    Son.prototype = Parent.prototype
    Son.prototype.constructor = Son
    

    2.类式继承

    function Parent(name){
            this.name = name
    }
    
    function Son(name,newName){
            this.newName = newName;
            Parent.call(this,name)
    }
    

    针对属性使用 类式继承
    针对方法是用原型继承
    使用es6 extends继承。
    继承方式可以有很多种,但是无论哪种,都是
    子类属性即父类的属性
    子类的方法继承父类的方法

    son.__ proto__ = parent
    son.prototype.__ proto__ = parent.prot0type

    相关文章

      网友评论

        本文标题:javascripts面向对象基础

        本文链接:https://www.haomeiwen.com/subject/samwjxtx.html