JavaScript中面相對象OOP

方法javascript

方法的原型鏈

<html>
<head>
    <title></title>
</head>
<script type="text/javascript">
    //原型鏈:a1對象(實例對象)還讓A.prototype對象(原型對象)之間的鏈接,叫作原型鏈
    //2個對象。之間有一個連接 _proto_
    //a1下是沒有num1(A中沒有this.num1=20),會繼續經過a1._proto_找num1。
    //a1下有num1(A中沒有this.num1=20),再也不會繼續經過a1._proto_找num1,
    //即便A.prototype.num1 = 10; alert(a1.num1);依然是20
    //....
    //原型鏈最外層:Object.prototype
    function A() {
        //this.num1=20
    }
    //A.prototype.num1 = 10;
    /*Function.prototype.num1 = 30;*/
    Object.prototype.num1 = 40;
    /*A.prototype.num1 = 60*/
    A.prototype.fun = function () {
        alert(this.num1)
    };
    var a1 = new A();
    a1.fun();
    alert(a1.num1);
</script>
<body>

</body>
</html>

建立 本質繼承

繼承:子對象的屬性修改,不能致使父對象的屬性的改變
1:Object.create(對象原型)
2:inherit4objfun
我畫了一張圖
html

<!DOCTYPE html>
<html lang="ZH-CN">
<head></head>
<script type="text/javascript">
    function inherit4fun(Child, Parent) {
        function F() {}; // 定義一個臨時函數
        F.prototype = Parent.prototype; // 把父類的原型賦給臨時函數的原型
        Child.prototype = new F(); // 把子類的原型賦值爲f的對象
    }
    function inherit4objfun(p){
          if(p == null) throw TypeError();
          //能夠不用es5中的Object.create
          //if(Object.create)return Object.create(p);
          var t = typeof p;
          if(t !== "object" && t !== "function") throw TypeError();
          function f(){}
          f.prototype = p;
          return new f();
    }
    function Person(name, age) {
        this.name = name;
        this.age = age;
        this.aler = function () {
             console.log(`Person.function-aler`);//``es6 的字符串  能夠換行
            // console.log(`Per
            // son.function-aler`);//``es6 的字符串  能夠換行
        }
    }
    //由於prototype是對象,能夠寫成無序鍵值對
    Person.prototype = {
        sayHi: function () {
            console.log('Person.prototype-sayhi');
        },
        sayHello: function () {
            console.log('Person.prototype-sayhello');
        }
    }
    function Student(sname, sage) {
        Person.call(this, sname, sage);
    }
    /*  錯誤重現1
        //Student.prototype = Person.prototype;
        //當修改Student.prototype時候,Person.prototype也會被修改
        //Student.prototype.saystu =function () {console.log('saystu');} 
    */
    /*  錯誤重現2
        //當改變Student.prototype時候,原來的會被覆蓋
        // Student.prototype = {
        //     saystu: function () {
        //         console.log('saystu');
        //     }
        // }
    */
    /*  正確重現1
        //當改變Student.prototype時候,原來的會被覆蓋,達不到子類繼承父類,或者子類原型能夠增長方法不影響到父類原型
        //此時就須要將二者的方法合併。-->將基類原型的方法拷貝到子類原型上 相似$.extend 拷貝繼承 (淺拷貝就行了,原型中通常存方法)
        // Student.prototype = new Person();
        // Student.prototype.constructor = Student;
        // Student.prototype.saystu =function () {console.log('saystu');} 
    */
    /*  正確重現2
        // inherit4fun(Student,Person);
        // Student.prototype.saystu =function () {console.log('saystu');} 
    */
    /*  正確重現3
    */
        Student.prototype=inherit4objfun(Person.prototype);
        Student.prototype.saystu =function () {console.log('saystu');} 
    
    /*  正確重現4 對象的繼承
    */
        var o={x:1}
        var childObj=inherit4objfun(o);
        childObj.y=2;
        console.log(childObj)//打印不出繼承的屬性。
        console.log(childObj.x+childObj.y)//3
    
    var stu1 = new Student("zg", 18);
    var p1 = new Person(" ls", 20);
    console.log(stu1,p1)
    //Student.prototype增長saystu方法,而後看Person.prototype是否增長,增長即是錯誤的
    console.log(Student.prototype,Person.prototype )
    stu1.aler();
    stu1.sayHi();
    stu1.sayHello();
    //stu1.saystu();
</script>
<body>
</body>
</html>

對象

叫法:散列 散列表 hash hashtable``字典 dictionary``關聯數組 associate array
種類:1,宿主對象(瀏覽器定義),dom對象 bom對象(window location navigatior),這些瀏覽器定義的方法能夠當成普通的js函數,能夠把宿主瀏覽器對象當成內置對象
2,內置對象(js定義)50多種。3,自定義對象
特性:擴展標記(是否能夠向改對象 添加新屬性)!!,類(class),原型(prototype)java

/*
    內置對象舉例 更多https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects
    錯誤       Error,EvalError,InternalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError 8種
    帶索引的集合Array,Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array 10種
    帶鍵的集合Map, Set ,WeakMap ,WeakSet 4種
    結構化數據ArrayBuffer ,SharedArrayBuffer, Atomics, DataView, JSON 5種
    控制抽象對象 Promise, Generator ,GeneratorFunction 3種
    反射 Reflect, Proxy 2種
    國際化ECMA腳本的多語言附加組件。Intl,Intl.Collator,Intl.DateTimeFormat,Intl.NumberFormat
    非標準對象Iterator ,ParallelArray ,StopIteration 
    其餘arguments
*/

console.log({}.toString.call(new Error()))               //[object Error]
console.log({}.toString.call(new SyntaxError('errmsg'))) //[object Error]

var buffer = new ArrayBuffer(2);
var a=new DataView(buffer)
console.log({}.toString.call(a))       //[object DataView]

function* gen() { yield 1;yield 2;yield 3;}
var g = gen()
onsole.log({}.toString.call(g))      //[object Generator]
console.log({}.toString.call(Infinity)) //[object Number]
console.log({}.toString.call(new Float32Array(2))) //[object Float32Array]

屬性(這裏真的很複雜)------------------

種類:繼承屬性(inherited property),自有屬性(own property)
屬性特性(property attribute)
1,數據屬性特性
可枚舉(enumerable) 默認true。for-in遍歷出,可配置(configurable),可寫(writable),值(value)
2,訪問器屬性特性
將數據屬性的 可寫特性換成set(val), get()方法function!
可枚舉(enumerable)默認true。for-in遍歷出,可配置(configurable),set(val)function,get()function
----

----es6

  定義屬性:Object.defineProperty(),Object.defineProperties()

  獲取屬性:getOwnPropertyDescriptor(obj,attr),getOwnPropertyDescriptors(obj)(參數只有對象,注意返回值)

/*
    不明確聲明,特性值默認false,value默認undefined, 區分經常使用方式
*/
//defineProperty
var obj={};
Object.defineProperty(obj,'a',{configurable:true})
//{configurable:true,enumerable:false,value:undefined,writable:false}
Object.getOwnPropertyDescriptor(obj,'a') 
/*
{
    a: Object
    __proto__: Object
}
*/
Object.getOwnPropertyDescriptors(obj) 
-------------------------------------------------------
//defineProperties
/*
    {
        a:{configurable:false,enumerable:false,value:undefined,writable:false},
        b:{configurable:false,enumerable:false,value:undefined,writable:false},
        __proto__:Object...
    }
*/
var obj={};
Object.defineProperties(obj,{a:{enumerable:false},b:{writable:false}})
Object.getOwnPropertyDescriptors(obj) 

-------------------------------------------------------
//經常使用默認true
Object.getOwnPropertyDescriptors({a:1},'a')//{configurable:true,enumerable:true,value:1,writable:true}

對象的可擴展Object.preventExtensions(o)(對象添加新屬性,注意不是編輯原來屬性)

var o={a:1};
o.b=2
console.dir(o)//{a:1,b:2}
Object.preventExtensions(o)
o.c=3
console.dir(o)//{a:1,b:2} 不可添加
o.b=4
console.dir(o)//{a:1,b:4} 能夠編輯

遍歷屬性名------------------

  自定義對象屬性都是可枚舉

  繼承對象的內置屬性都是不可枚舉

  1,for in

  2,Object.keys(obj)

  3,Object.getOwnPropertyNames(obj) 查看隱藏不可枚舉屬性比較有用

var parentObj={a1:'a1'};
Object.defineProperties(parentObj,{a2:{enumerable:true,value:'a2'},a3:{enumerable:false,value:'a3'}})

var childObj=inherit4objfun(parentObj);
childObj.b1='b1';
Object.defineProperties(childObj,{b2:{enumerable:true,value:'b2'},b3:{enumerable:false,value:'b3'}})

/* ------------------------------------------                    for in       自己,繼承,可枚舉                 ---------------------------------------------------- */
for(var attr in childObj){console.info(`自身和繼承的枚舉屬性`+attr)}//a1 a2 b1 b2
/* ------------------------------------------                    Object.keys(obj)  自己,可枚舉                  ---------------------------------------------------- */
console.log(`自身的枚舉屬性`+Object.keys(childObj))//["b1", "b2"]
/* ------------------------------------------        Object.getOwnPropertyNames(obj)  自己全部屬性,包括不可枚舉---------------------------------------------------- */
console.log(`自身的全部屬性,包括不可枚舉`+Object.getOwnPropertyNames(childObj))//["b1", "b2"]

var arr=[6,'a']
Object.getOwnPropertyNames(arr)//["0", "1","length"]

Object.getOwnPropertyNames(Object.prototype)
//["__defineGetter__", "__defineSetter__", "hasOwnProperty", "__lookupGetter__", "__lookupSetter__", "propertyIsEnumerable", "constructor", "toString", "toLocaleString", "valueOf", "isPrototypeOf", "__proto__"]

Object.getOwnPropertyNames(Object)
//["length", "name", "arguments", "caller", "prototype", "assign", "create", "getOwnPropertyDescriptor", "getOwnPropertyNames", "getOwnPropertySymbols", "is", 
//"preventExtensions", "seal", "defineProperties", "defineProperty", "freeze", "getPrototypeOf", "isExtensible", "isFrozen", "isSealed", "keys", "setPrototypeOf", "entries", "values", "getOwnPropertyDescriptors"]

檢測屬性------------------

  除了for in ,要先知道屬性名字,輸入名字 檢測。檢測和遍歷的區別

  for in 帶有遍歷功能 自帶檢測功能

  1,for in 自有和繼承的枚舉屬性

  2,hasOwnProperty()自有屬性 包括不可枚舉的

  3,propertyIsEnumerable()是hasOwnProperty()加強版 1自有屬性,2可枚舉

childObj.hasOwnProperty('a1')//false 繼承不能檢測
childObj.hasOwnProperty('a3')//false
childObj.hasOwnProperty('b1')//true
childObj.hasOwnProperty('b3')//true 自有不可枚舉的也能檢測出來

childObj.propertyIsEnumerable('a1')//false 繼承不能檢測
childObj.propertyIsEnumerable('a3')//false 
childObj.propertyIsEnumerable('b1')//true  只有自有可枚舉屬性
childObj.propertyIsEnumerable('b3')//false

刪除

//防止內存泄漏
var a={b:{c:0}}
//delete b.c
delete a.b//切斷b屬性(對象)與宿主a(對象)的聯繫   刪除的b對象的引用{{c:0}}依然存在 要檢測遍歷b屬性中是否含有屬性,再遞歸檢測屬性是否含有屬性,直到最後不含有。防止內存泄漏
//假如從var a={b:{c:{d:{e:1}}}}刪除b屬性
//從裏到外刪除
//delete a.b.c.d.e
//delete a.b.c.d
//delete a.b.c
//delete a.b
var o={a:1};
var c;
Object.defineProperty(o,'b',{configurable: false,
            enumerable: true,
            get: function () {
                return 11;
            },
            set: function proxySetter(newVal) {
                
            }})
o.b=8
相關文章
相關標籤/搜索