天天看点

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>