黑马视频-JavaScript高级 1

2019-08-26  本文已影响0人  璎珞纨澜

1. JavaScript 基础介绍

1.1 JavaScript 是什么?

JS 分为三个部分

组成部分 说明
Ecmascript 描述了该语言的语法和基本对象
DOM 描述了处理网页内容的方法和接口
BOM 描述了与浏览器进行交互的方法和接口

1.2 基本概念

1.3 JavaScript 中的数据类型

JavaScript 有 5 种简单数据类型:Undefined、Null、Boolean、Number、String 和 1 种复杂数据类型 Object

基本类型(值类型)

复杂类型(引用类型)

类型检测

值类型和引用类型在内存中的存储方式

值类型复制和引用类型复制

值类型和引用类型参数传递

值类型与引用类型的差别

JavaScript 执行过程

JavaScript 运行分为两个阶段:

先预解析全局作用域,然后执行全局作用域中的代码。
在执行全局代码的过程中遇到函数调用就会先进行函数预解析,然后再执行函数内代码。


2. JavaScript 面向对象编程

2.1 编程思想

2.2 面向对象的特性

2.3 创建对象的三种方式

  1. 字面量的方式
var per1 = {
    name:"小张",
    age:20,
    sex:"男",
    readBook:function(){
        console.log("西游记")
    }
}
  1. 调用系统的构造函数方法
var per2 = new Object()
per2.name="小张"
per2.age=20
per2.sex="男"
per2.readBook=function(){
    console.log("西游记")
}

以上两种方式都是不能确定创建出来的对象是什么类型的

  1. 自定义构造函数
function Person(name,age,sex){
    this.name = name
    this.age = age
    this.sex =sex
    this.readBook= function () {
        console.log("西游记")
    }
}
var per = new Person("小张",20,"男")
console.log(per instanceof Person)

结果输出 true

  1. 工厂模式创建对象
function createObejct(name, age, sex) {
    var obj = new Object()
    obj.name = name
    obj.age = age
    obj.sex = sex
    obj.readBook = function(){
        console.log("西游记")
    }
    return obj
}
var per1=createObejct("小明",20,"男")

自定义构造函数与工厂模式的共同点与不同点:

2.4 构造函数与实例对象之间的关系

面向对象的思想是:抽象的过程 --> 实例化的过程
自定义构造函数 --> 使用构造函数实例化对象

function Animal(name) {
    this.name = name
}
var dog = new Animal("大黄")
console.dir(dog)
console.dir(Animal)
执行结果
console.log(dog instanceof Animal) // true
console.log(dog.constructor == Animal) // true
console.log(dog.__proto__.constructor == Animal) // true
console.log(dog.__proto__.constructor == Animal.prototype.constructor) // true

总结:

  1. 实例对象是通过构造函数构建的 --- 创建的过程叫做实例化
  2. 如何判断对象是不是这个数据类型?

2.5 原型的引入

首先我们来看构造函数创建对象带来的问题:

function Person(name,age,sex){
    this.name = name
    this.age = age
    this.sex = sex
    this.readBook = function () {
        console.log("西游记")
    }
}
var per1 = new Person("小张",20,"男")
var per2 = new Person("小杨",25,"女")
per1.readBook()
per2.readBook()
console.log(per1.readBook == per2.readBook)
执行结果

为什么 per1 和 per2 的 readBook 不相等呢?是因为使用构造函数每创建一个对象就会开辟一块内存空间,而这个对象指向自己对应的那块内存空间。如果我new了100个对象,那么对应的就有一百块内存空间中有一样的 readBook 方法。这样就开辟了大量的控件,浪费内存。那么我们通过原型来解决这个问题。

function Person(name,age,sex){
    this.name = name
    this.age = age
    this.sex = sex
}
Person.prototype.readBook = function(){
    console.log("西游记")
}
var per1 = new Person("小张",20,"男")
var per2 = new Person("小杨",25,"女")
per1.readBook()
per2.readBook()
console.log(per1.readBook == per2.readBook)
image.png

2.6 构造函数、实例对象和原型对象的关系

通过下面这张图来解释这三者的关系:


构造函数、实例对象和原型对象的关系

2.7 利用原型共享数据

不需要共享的数据写在构造函数中,需要共享的数据写在原型中。

function Student(name,age,sex){
    this.name = name
    this.age = age
    this.sex = sex
}
Student.prototype.major = "计算机"
Student.prototype.teacher = "王老师"
Student.prototype.study = function(){
    console.log("学Javascript")
}
Student.prototype.readBook = function(){
    console.log("看编程书")
}
var stu = new Student("小张",20,"男")
console.dir(Student)
console.dir(stu)
执行结果

上面的代码还可以将 prototype 写成一个对象,但是需要在原型对象中需要手动添加构造器为当前的构造函数:

function Student(name,age,sex){
    this.name = name
    this.age = age
    this.sex = sex
}
Student.prototype = {
    constructor: Student, //需要手动添加构造器
    major: "计算机",
    teacher: "王老师",
    study: function(){
        console.log("学Javascript")
    },
    readBook: function(){
    console.log("看编程书")
    }
}
var stu = new Student("小张",20,"男")
console.dir(Student)
console.dir(stu)

2.8 原型中的方法是可以相互调用的

我们知道实例对象的方法是可以相互调用的,像这样:

function Person(name,age,sex){
    this.name = name
    this.age = age
    this.sex = sex
    this.readBook = function () {
        console.log("西游记")
        this.writeBlog()
    }
    this.writeBlog = function() {
        console.log("写观后感")
    }
}
var per = new Person("小张",20,"男")
per.readBook()
执行结果

如果把方法定义在原型中,能不能相互调用呢?
原型中的方法是可以相互调用的。

function Animal(name,age) {
  this.name=name
  this.age=age
}
//原型中添加方法
Animal.prototype.eat=function () {
  console.log("动物吃东西")
  this.play()
}
Animal.prototype.play=function () {
  console.log("玩球")
  this.sleep()
}
Animal.prototype.sleep=function () {
  console.log("睡觉了")
}

var dog=new Animal("小苏",20)
dog.eat()
执行结果

2.8 实例对象使用属性和方法层层的搜索

实例对象的用到的属性或者方法先在实例对象中找,找到了则直接使用,如果在实例对象中找不到就会去实例对象的__proto__指向的构造函数的原型对象 prototype 中找,找到了则使用,如果原型对象也没有就会报错不存在。

2.9 为内置对象添加原型方法

我们能否为系统的对象的原型添加方法,这相当于在改变源码。
比如,我希望字符串中有一个倒序字符串的方法,就可以直接在 String 内置对象的原型对象上添加自己的 myReverse 方法:

String.prototype.myReverse=function () {
  for(var i=this.length-1;i>=0;i--){
    console.log(this[i]);
  }
}
var str="abcdefg"
str.myReverse()

或者是为 Array 内置对象增加自己的冒泡排序方法:

Array.prototype.mySort=function () {
  for(var i=0;i<this.length-1;i++){
      for(var j=0;j<this.length-1-i;j++){
          if(this[j]<this[j+1]){
              var temp=this[j]
            this[j]=this[j+1]
            this[j+1]=temp
          }
      }
  }
}
var arr=[100,3,56,78,23,10]
arr.mySort()
console.log(arr)

系统内置对象的属性和方法可能不满足现在需求,所以,为了方便开发,可以通过原型的方式加入属性或者方法。

上一篇 下一篇

猜你喜欢

热点阅读