天天看點

js 對象原型鍊

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script type="text/javascript">
        //對象建立
        //1、單例模式:    /*對象資料類型的作用:把描述同一個事物(同一個對象)的屬性和方法放在一個記憶體空間下,起到了分組的作用,這樣不同僚物之間的屬性即使用屬性名相同,互相也不會發生沖突 我們把這種分組編寫代碼的模式叫做單例模式,在單例模式中我們把p1 p2也叫做命名空間  */
        var p1 = {
            name: "aa",
            age: 12
        };
        var p2 = {
            name: "bb",
            age: 22
        };
        //2、工廠模式:函數封裝
        function createJsPerson(name, age) {
            var obj = {};
            obj.name = name;
            obj.age = age;
            obj.writeJs = function() {
                console.log("my name is " + this.name + ",start study js");
            };
            return obj;
        };
        var zs = createJsPerson("zhangsan", 12);
        zs.writeJs();
        var ls = createJsPerson("lisi", 16);
        ls.writeJs();
        //3、js是一種輕量級程式設計語言 封裝 繼承 多态  html css是标記語言 js沒有方法重載 (但通過方法getNum可以類似實作重載)
        function getNum(num) {
            if (typeof num == "undefined") {
                return 0;
            }
            return num;
        };
        getNum(); //類似實作重載了
        getNum(100);
        //4、構造函數模式:建立一個自定義類,并且建立這個類的執行個體
        //與工廠模式差別:1、工廠模式建立對象 createJsPerson("zhangsan", 12) 構造函數模式 new Person("zhangsan", 12) 2、構造函數模式不需要手動建立對象,浏覽器預設會建立目前類的執行個體this并傳回 3、若構造函數模式有手動傳回基本資料類型(return 100)的則目前執行個體沒影響 若手動傳回了一個對象{name:"ccc"}則目前執行個體為手動傳回的對象
        //js中所有的類都是函數資料類型的,所有的類的執行個體都是對象類型
        function Person(name, age) {
            this.namex = name;
            this.age = age;
            this.writeJs = function() {
                console.log("my name is " + this.namex + ",start study js");
            }
        };
        var p1 = new Person("zhanghai", 33); //var pp1=Person("lisi",22) 此處pp1 undefined 
        p1.writeJs();

        function Fn() {
            var num = 10; //是方法私有變量與Fn執行個體fn1沒有任何關系
            this.namexx = "dddd"; //this->fn1
            this.getName = function() {
                console.log(this.namexx); //this需看getName執行進修才知道
            };
            this.fun1 = function() {
                console.log(this.namexx);
            }
        };
        var fn1 = new Fn; //預設類沒有參數new時小括号可以省略
        fn1.getName(); //輸出"dddd"
        var ss1 = fn1.fun1;
        ss1(); //輸出 undefined this-》window
        console.log(fn1.getName === fn1.getName); //false name getName都是執行個體的私有屬性,若要有公共屬性需要用原型鍊
        console.log(fn1.num); //輸出 undefined
        console.log("name" in fn1); //in 檢測某一屬性是否屬于這個對象,不管是私有的屬性還是公有的屬性
        console.log(fn1.hasOwnProperty("name")); //hasOwnProperty:用來檢測某一屬性是否為這個對象的私有屬性,隻檢測私有屬性
        //5、基于構造函數模式的原型鍊:1、每一個函數資料類型(普通函數、類)都有一個天生自帶的屬性prototype,并且這個屬性是一個對象類型的,2、并且浏覽器在prototype增加了一個constructor(構造函數),屬性值是目前函數本身。3、每一個對象類型(普通對象,prototype,執行個體)也天生自帶一個屬性__proto__,其屬性值是目前執行個體類的原型prototype
        function Animal() {
            this.age = 4;
            this.show = function() {
                console.log(this.age);
            };
        };
        Animal.prototype.pp = function() {
            console.log("ddddd", this.age)
        };
        var animal1 = new Animal();
        console.log(Animal.prototype)
        console.log(animal1.__proto__.constructor)
    Animal.prototype.pp==animal1.__proto__.pp //true
    </script>
</body>

</html>      
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script type="text/javascript">
        function Fn() {
            this.num = 10;
        };
        Fn.prototype = { //自定義Fn原型會,若内置的類原型不允許自定義,但也可改部分Array.prototype.sort=function(){}
            constructor: Fn,
            a: function() {

            },
            b: function() {

            }
        };
        var fn = new Fn;
        console.log(fn);
        var obj = {
            name: "howhy",
            age: 22
        };
        obj.__proto__.aaa = function() {
            console.log(4444);
        };
        for (var key in obj) { //預設會把自己私有的和自己所屬類原型上擴充的屬性和方法周遊
            if (obj.propertyIsEnumerable(key)) { //propertyIsEnumerable 私有屬性 hasOwnProperty
                console.log(obj[key]); // "howhy" 22
            }
        };
        var obj2 = Object.create(obj); //将對象obj作為obj2對象的原型
        //原型繼承 子類若将繼承父類所有屬性和方法 則需将子類的prototype=父類的執行個體 這樣的父類公有+私有都成了子類公有的
        function A() {
            this.x = 10;

        }
        A.prototype.getX = function() {
            console.log(this.x);
        }

        function B() {
            this.getY = function() {
                console.log(2222)
            }
        }
        B.prototype = new A;
        var b = new B();
        b.getX();
        //call apply bind
        function fun() {
            console.log(this)
        }
        Function.prototype.mycall = function(context) {
            this();
            // this.name = this;
            // this.name();
            context[this.name] = this();
            console.log(context)

        }
        fun();
        fun.call({})
        fun.mycall({})
    </script>
</body>

</html>