JS对象与原型

前端开发 作者: 2024-08-23 10:15:01
一. JS的对象 1.1 创建对象的几种方式 1.1.1 通过字面量创建对象 在js中,一对 其实就是一个对象 1.1.2 通过系统的构造函数 通过系统的构造函数创建一个空的对象,然后用js动态语言的

1.1 创建对象的几种方式

1.1.1 通过字面量创建对象

var person = {
            name: "tom",age: 23,read: function () {
                console.log(name,": read book")
            }
        }

1.1.2 通过系统的构造函数

  			var person2 = new Object()
        person2.name = "jerry"
        person2.age = 23
        person2.say = function () {
            console.log(person2.name,": say hello")
        }

1.1.3 通过自定义构造方法

			 function Person(name,age,sex) {
            this.name = name
            this.age = age
            this.sex = sex
            this.say = function () {
                console.log(this.name," :say hello")
            }
        }

				// 创建对象时,使用 new 关键字
		    p = new Person("tom",23,"man")
        console.log(p instanceof Person)
  1. 开辟空间
  2. 将this设置成当前对象
  3. 初始化属性和方法
  4. 将this返回

1.1.4 工厂模式创建对象

     function Person(name,sex) {
            // new Object 作为当前的返回值
            var obj  = new Object()
            obj.name = name
            obj.age = age
            obj.sex = sex
            obj.say = function () {
                console.log(this.name," :say hello")
            }
       			// 手动将对象返回出去
            return obj
        }
				// 工厂模式创建对象,不需要使用new 关键字
        var p =  Person("tom","man")
        console.log(p instanceof Person) // false

1.2 构造函数与实例对象

   			// 构造函数和实例的关系
        function Person(name) {
            this.name = name
            this.say = function () {
                console.log(this.name," :say hello")
            }
        }

        // 对象p是通过 自定义的构造函数Person创建出来的
        var p = new Person("tom")

        console.dir(p)
        console.dir(Person)
  • 实例对象的__proto__属性中有constructor属性,上面记录着自己的构造方法。
  • Person是构造方法,也是对象,我们直接打印Person得到的结果中有个属性prototype,它里面也有个属性叫做 constructor。里面记录着构造方法就是自己本身。
  • 结合上面的例子,我们其实可以得到这样的推断,实例对象的原型属性 和 构造函数的原型属性中的constructor都指向了同一个构造方法 ,然后可以进一步推断 p是Person类型
 			  console.log(p.constructor === Person) // true
        console.log(p.__proto__.constructor == Person) // true
        console.log(p.__proto__.constructor == Person.prototype.constructor) // true
        // 由此推断出,p === Person
        console.log(p instanceof Person) // true

2.1 引入原型的必要性

  			// 构造函数创建对象带来的问题
        function Person(name) {
            this.name = name
            this.say = function () {
                console.log(this.name,": say hello")
            }
        }

        var p1 = new Person("tom")
        var p2 = new Person("jerry")

        p1.say()  // tom : say hello
        p2.say() //  jerry : say hello

        // todo 返回false, 表示说,p1和p2的say方法,并不是同一份, 其实这并不是一件好事
        console.log(p1.say == p2.say)
			 // 共享函数,引出原型
        function Say() {
            console.log(this.name,": say hellp")
        }

        function Person(name) {
            this.name = name
            this.say = Say
        }

        var p1 = new Person("tom")
        var p2 = new Person("jerry")

        p1.say()// tom : say hellp
        p2.say()// jerry : say hellp

        // 这样的话,确实能实现节省空间,但是容易出问题
        console.log(p1.say == p2.say) // ture

2.2 认识原型

				function Person(name) {
            this.name = name
        }

        // 在原型上添加方法
        // 为什么可以说原型是对象呢? 想想js中一个对象可以通过 点 , 动态点添加属性和方法?
        Person.prototype.say = function () {
            console.log(this.name,":say hello")
        }

        var p1 = new Person("tom")
        var p2 = new Person("jerry")

        p1.say()//tom :say hello
        p2.say()//jerry :say hello
        console.log(p1.say == p2.say) // true
   		  console.dir(p1)
        console.dir(p2)
        console.dir(Person)
  • 实例对象中的直接拥有的标准属性,比如name, 这些都是直接出现在构造方法中的属性,而且这些属性是js对象所私有的。
  • 上图中实例对象有个属性叫做:__proto__,这个属性是用来给浏览器使用的,而不是给程序员使用,所以我们称它为非标准属性。 此外谷歌浏览器是支持这个属性的,但是在IE8浏览器中,我们执行这句console.log(p1.__proto__) 会报错,说undefined

2.3 原型,实例对象,构造函数之间到底是什么关系呢?

2.4 关于this对象

  • 看下面的第一个例子
 			  function Person(name) {
            // 考虑一下,这个this是谁?
            this.name = name
            console.log(this)
        }

        var p = new Person("tom")
  • 看下面的第二个例子
      	function Person(name) {
            // 考虑一下,这个this是谁?
            this.name = name
            console.log("n10: ",this)
        }

        Person.prototype.say = function () {
            // todo 这里的this指的是谁呢?
            // 首先,方法是添加在原型对象上, 那么this指的是原型对象吗?
            // 通过控制台可以看到,this.name ,其实不是原型对象,而是say()方法的调用者(实例对象)
            console.log("n16: ",this.name,": say hello")
        }

        var p1 = new Person("tom")
        var p2 = new Person("jerry")

        p1.say()
        p2.say()
  • 看下面的第三个例子:
    // 用面向对象的方式封装构造函数
    function ChangeStyle(btnId,dvId,color) {
        this.btnObj = document.getElementById(btnId)
        this.dv = document.getElementById(dvId)
        this.color = color
    }

    // 在构造方法的原型上添加方法
    ChangeStyle.prototype.init = function () {
        // 这里面的this表示的是 调用init方法的实例对象
        var that = this
        this.btnObj.onclick = function () {
            // todo  为什么原型中的函数中,就不能使用this,而是that呢???
            // todo  或者问下,当前函数中的this是谁呢?
            that.dv.style.backgroundColor = that.color
        }
    }

2.5 其他原型的写法

  • 最常见的写法就是像下面这样,在当前原型的基础上添加属性或者方法
 		function Person(name) {
        this.name = name
    }

    // 前面的例子中我们都是像下面这样写代码, 这其实是对原来的  原型对象属性的累加
    // 原来的原型对象中有个属性,叫做consturctor
    Person.prototype.say  = function(){
        //todo
    }
  • 也可以像下面这样
   Person.prototype = {
        constructor:Person,// 手动修改构造器的指向
        height:"20",weight:"20",say:function () {
            // todo
        }
    }

2.6 方法之间的相互访问

  • 构造函数中的成员方法是可以相互访问的。
   function Person(name) {
        this.name = name
        this.say = function () {
            console.log("say")
            // 通过这个例子,可以看到,对象的方法中可以直接调用对象的方法
            this.eat()
        }
        this.eat = function () {
            console.log("eat")
        }
    }
  • 原型中的方法也是可以相互访问的。
    function Person(name) {
        this.name = name
    }

    Person.prototype.say  = function(){
        console.log("say")
        // 原型中的方法也可以相互访问
        this.eat()
    }

    Person.prototype.eat  = function(){
        console.log("eat")
    }

    var p1 = new Person("tom")
    p1.say()

2.7 覆盖内置对象原型中的方法

	  // 在现有的js封装类上干这件事,也算是在修改源码
    String.prototype.myReverse = function () {
        for (var i = 0; i < this.length; i++) {
            console.log("发生倒叙")
        }
    }
    var str = "123"
    str.myReverse()
原创声明
本站部分文章基于互联网的整理,我们会把真正“有用/优质”的文章整理提供给各位开发者。本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
本文链接:http://www.jiecseo.com/news/show_67188.html
JS对象与原型