JavaScript 原型对象prototype和new的工作原理

面向对象

面向对象编程介绍

1. 面向对象 : 是 一种解决问题 注重结果的思维方式

面向过程 : 注重的是过程,就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次 调用就可以了。

优点:性能比面向对象高,适合跟硬件联系很紧密 的东西,例如单片机就采用的面向过程编程。

缺点:没有面向对象易维护、易复用、易扩展

面向对象(oop) : 注重的是结果,是把事务分解成为一个个对象,然后由对象之间分工与合作。

优点:易维护、易复用、易扩展,由于面向对象有封装 、继承、多态性的特性,可以设计出低耦合的系统,使 系统 更加灵活、更加易于维护

缺点:性能比面向过程低

面向对象的特性: 封装性 ,继承性 ,多态性

2. 面向对象 :本质 是对面向过程的封装

内置对象:

js作者提前封装好的对象,方便开发者直接使用

数组对象:

1. arr.concat(数组) : 把两个数组连接成一个数组

应用场景: 一般用于长列表(下一页),不断往后面拼接数组

//声明数组
let arr = [10,20,30,40,50]
 arr = arr.concat([66,34,56,70])
        console.log(arr)

2. arr.reverse() : 翻转数组

应用场景: 价格从低到高 切换成 从高到低, 只需要翻转数组即可

arr.reverse()
        console.log(arr)

3. arr.join('分隔符') : 把数组每一个元素拼接成字符串

应用场景 : 有些歌曲是多个人合唱,服务器会给我们一个数组。 这个时候就需要将数组元素通过join拼接起来然后再页面显示

let str = arr.join('|')
       console.log(str)

4. arr.sort( function(a,b){return a-b} ) : 排序

let arr1 = [12,45,67,89]
         arr1.sort(function(a,b){
             // return a-b // 从小到大
             return b-a  //从大到小
         })
        
        console.log(arr1)

字符串对象:

//声明一个数组
 let str = '黑马程序员武汉大前端女神节快乐!'

1. 字符串类似于数组,也有长度和下标

console.log( str.length )//16
console.log( str[5] )//武

2. str.indexOf('字符串') 获取 ‘字符串’ 在str中的首字母下标

如果字符串存在则返回首字母下标, 如果字符串不存在则返回固定值 -1

应用场景: 一般用户判断 str中是否有某个字符串 如果没有则返回-1,不是-1说明有

let index1 = str.indexOf('大前端')
        console.log( index1 )//7
        let index2 = str.indexOf('大女神')
        console.log( index2 )//-1

3. str.split('分隔符') 用分隔符切割字符串,得到切割之后的数组

应用场景 : 一般用户解析 网址

let url = 'http://www.baidu.com?name=张三&age=20'
      console.log( url.split('|') )//['http://www.baidu.com?name=张三&age=20']
      console.log( url.split('?') )//['http://www.baidu.com', 'name=张三&age=20']
      console.log( url.split('=') )//['http://www.baidu.com?name', '张三&age', '20']

4. str.substr(起始下标,截取长度) 截取字符串

应用场景 : 一般后台返回的数据 不会和前端完全匹配。 有时候需要自己截取一部分

例如: 商品价格后台返回 :价格58元 但是前端只需要显示58元,就需要截取

 console.log( str.substr(2,5) )//从2下标开始,往后截取5个字 程序员武汉

5.大小写转换 (中文没有大小写)

toLocaleLowerCase() 转换小写 

toLocaleUpperCase()转换大写

应用场景: 字母验证码不区分大小写 (一般无论你输入什么,都会转成大写或小写保持格式统一)

 console.log('dsSFJSGDJHsdfs'.toLocaleLowerCase() )//小写 dssfjsgdjhsdfs
 console.log('dsSFJSGDJHsdfs'.toLocaleUpperCase() )//大写 DSSFJSGDJHSDFS

原形对象

工厂函数:用于创建对象的函数

例子:

function createPerson(name,age,sex){
            // 创建对象
            let p = {}
            // 对象赋值
            p.name = name
            p.age = age
            p.sex = sex
            // 返回这个对象
            return p 
        }
        let p1 = createPerson('千玺',20,'男')
        let p2 = createPerson('王源',20,'男')
        let p3 = createPerson('王俊凯',20,'男')
        console.log(p1,p2,p3)

构造函数:是使用new调用一个函数

                  构造函数作用与工厂函数一致,都是用来创建对象的。但是代码更加简洁。

构造函数new的工作原理:(重点面试题)

(1)创建一个对象,默认是空的

(2)this指向这个对象

(3)对象赋值

(4)返回这个对象

构造函数new在使用时需要注意的地方:(加分项)

1.构造函数首字母一般大写, 为了提醒调用者不要忘记new关键字

2.如果在构造函数内部 手动return

       return 值类型 : 无效,还是返回new创建的对象

       return 引用类型 : 有效,会覆盖new创建的对象

例子:


        function Person(name,age,sex){
            //(1)创建空对象   {}
            //(2)this指向这个对象  this = {}
            //(3)对象赋值
            this.name = name
            this.age = age
            this.sex = sex
            //(4)返回这个对象 return this
        }

        let p1 = new Person('千玺',20,'男')
        console.log(p1)

原型对象(构造函数资源浪费)

(1)构造函数内部方法: 浪费内存资源

 function Person(name,age){
          this.name = name
          this.age = age
          this.eat = function(){
              console.log('eat');

          }
      }

      let p1 = new Person('张三',18)
      let p2 = new Person('李四',20)
      console.log( p1,p2)
 /* 思考: p1和p2都有eat方法,而是函数体相同。但是他们是同一个函数吗?
      不是同一个: 因为每一次调用构造函数, 内部都会执行一次function,就会在堆中开辟一个新的空间。虽然代码是一样的,但是地址不同。 就会导致每调用一次构造函数,多出一个函数堆空间。导致内存资源浪费
      */
      console.log( p1.eat == p2.eat )//false

原型对象 :prototype

1.原型对象是 : 任何函数在声明的时候,系统会自动帮你创建一个对象,称之为原型对象

2.原型对象作用是 : 解决 内存浪费 + 变量污染

3.原型对象相关三个属性 ;  构造函数、原型对象、实例对象,

三者关系 (重点面试题)

prototype : 属于构造函数, 指向原型对象

__proto__ : 属于实例对象,指向原型对象  __proto__就是prototype

constructor : 属于原型对象,指向构造函数

(1)构造函数(是用new调用的函数)

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

(2)原型对象 prototype

console.log(Person.prototype)
      Person.prototype = {
        eat: function() {
          console.log("吃东西")
        },
        learn: function() {
          console.log("学习")
        }
      }

(3)实例对象 : 用new调用构造函数,返回的那个对象(new创建的那个对象)

let p1 = new Person('张三',20)
      console.log( p1 )

      let p2 = new Person('李四',22)
      console.log( p1.eat == p2.eat )//true

思维图:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5qKm6L-q4oCUMA==,size_20,color_FFFFFF,t_70,g_se,x_16

静态成员与实例成员

静态成员 和 实例 (属性+方法)

静态成员: 属于自己的函数成员

实例成员: 属于实例对象的成员

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

       let p1 = new Person('张三',20)
       console.log( p1.name )//实例成员
       console.log( p1.age )//实例成员

       console.log( Person.prototype )//静态成员
       console.log( Math.PI ) //静态成员 //内置对象-Math 
       console.log(Date.now())//静态成员 // Date.now()时间戳

    //获取对象的属性值 :object.values(对象)
   const arr = Object.values(p1)
   console.log(arr)

1.变量作用域 :

变量 作用的范围

2. js中有三种作用域

(1)全局作用域(Script) : 页面任何地方使用

全局变量 : 大括号外面声明

(2)局部作用域(Local) : 只能在函数内部使用

局部变量: 函数内部声明的变量(形参也是局部变量)

(3)块级作用域(Block) : 在大括号(分支+循环)里面声明的变量

3.作用域链 :

* 默认情况下,js代码处在全局作用域(顶级作用域:0级),当我们声明一个函数的时候,就会开辟一个局部作用域(1级)。 如果在局部作用域中又声明函数,就会形成新的局部作用域(2级),以此类推,形成链式结构。称之为作用域链。

4.变量访问作用域链规则 : 就近原则

* 自己作用域有声明,就访问自己的。 自己没有就找上级作用域声明,如果有则访问,没有继续往上找。如果找到最顶级(0级),还是找不到。 就会报错 xxx is not defined

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值