JavaScript高级第1天 (上):基础复习、对象、原型及原型链

课程介绍

课程大纲

在这里插入图片描述

基础复习

串讲

  • 变量
    • 变量的作用,语法,命名规则
  • 数据类型
    • 基本数据类型
    • 复杂数据类型
  • 类型转换
    • 转换成字符串
    • 转换成数字
    • 转换成布尔值
  • 运算符
    • 算术运算符
    • 赋值运算符
    • 比较运算符
    • 逻辑运算符
    • 自增自减运算符
    • 运算符的优先级
  • 流程控制语句
    • 顺序结构
    • 分支结构
    • 循环结构
  • 数组
    • 创建数组的两种方式
    • 下标和长度
    • 取值和存值
  • 函数
    • 声明和调用
    • 形参和实参
    • 返回值
  • 对象
    • 创建对象的方式
    • 属性和方法
    • 存值和取值
    • 对象的遍历
    • 操作对象属性的两种方式
  • 内置对象
    • Math
    • Array
    • Date
    • String

typeof关键字

typeof操作符返回一个字符串,返回的是操作数的类型

  • typeof 基本类型返回的是字符串

  • typeof 对象 返回的是object

  • typeof 函数 返回的是function

  • typeof null 返回的object

逻辑中断

&&:从左到右的顺序进行判断,如果发现某个操作数的逻辑判断是false,那么就不用继续判断了。

||:从左到右的顺序进行判断,如果发现某个操作数的逻辑是true,那么就不用继续判断了。

function fn (n1, n2) {
  n1 = n1 || 0
  n2 = n2 || 0
  console.log(n1 + n2)
}

值类型与引用类型

值类型:简单类型,变量在存储的时候,存储的是值本身。

引用类型:复杂类型,变量在存储的时候,存储的是对象的地址。

  • 值类型与引用类型(画图说明)
var num = 10;

var obj = {
  name:"zs",
  age:18
}

var people = {
  name:"zs",
  age:18,
  car:{
    brand:"forever",
    color:"green"
  }
}
  • 值类型与引用类型赋值特征(画图说明)

值类型赋值的时候,把值进行赋值

引用类型赋值的时候,赋值的是地址。

var num1 = 10;
var num2 = num1;
num2 = 99;
console.log(num1);
console.log(num2);

var obj1 = {
  name:"zs"
}
var obj2 = obj1;
obj2.name = "ls";
console.log(obj1.name);
console.log(obj2.name);


var obj1 = {
  name:"zs",
}
var obj2 = obj1;
obj1 = {
  name: 'ww'
}
obj2.name = "ls";

console.log(obj1.name);
console.log(obj2.name);

学习资源

  • JavaScript 高级程序设计(第三版)
    • 前端的红宝书
    • 建议每一个前端都完整的看一遍
  • JavaScript面向对象编程指南(第2版)
  • JavaScript面向对象精要
  • JavaScript 权威指南
  • JavaScript 语言精粹
  • 你不知道的 JavaScript

对象、原型、原型链

创建对象的方式

内置构造函数创建

我们可以直接通过 new Object() 创建:

//在js中,对象有动态特性,可以随时的给一个对象增加属性或者删除属性。
var person = new Object()
person.name = 'Jack'
person.age = 18

person.sayName = function () {
  console.log(this.name)
}

缺点:麻烦,每个属性都需要添加。

对象字面量创建

var person = {
  name: 'Jack',
  age: 18,
  sayName: function () {
    console.log(this.name)
  }
}

缺点:如果要批量生成多个对象,应该怎么办?代码很冗余

简单改进:工厂函数

我们可以写一个函数,解决代码重复问题:

function createPerson (name, age) {
  return {
    name: name,
    age: age,
    sayName: function () {
      console.log(this.name)
    }
  }
}

然后生成实例对象:

var p1 = createPerson('Jack', 18)
var p2 = createPerson('Mike', 18)

缺点:但却没有解决对象识别的问题,创建出来的对象都是Object类型的。

继续改进:构造函数

构造函数是一个函数,用于实例化对象,需要配合new操作符使用。

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

var p1 = new Person('Jack', 18)
p1.sayName() // => Jack

var p2 = new Person('Mike', 23)
p2.sayName() // => Mike

而要创建 Person 实例,则必须使用 new 操作符。
以这种方式调用构造函数会经历以下 4 个步骤:

  1. 创建一个新对象
  2. 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象)
  3. 执行构造函数中的代码
  4. 返回新对象

构造函数需要配合new操作符使用才有意义,构造函数首字母都需要大写

构造函数的缺点

使用构造函数带来的最大的好处就是创建对象更方便了,但是其本身也存在一个浪费内存的问题:

function Person (name, age) {
  this.name = name
  this.age = age
  this.type = 'human'
  this.sayHello = function () {
    console.log('hello ' + this.name)
  }
}

var p1 = new Person('lpz', 18)
var p2 = new Person('Jack', 16)
console.log(p1.sayHello === p2.sayHello) // => false

解决方案:

function sayHello() {
  console.log('hello ' + this.name)
}

function Person (name, age) {
  this.name = name
  this.age = age
  this.type = 'human'
  this.sayHello = sayHello
}

var p1 = new Person('lpz', 18)
var p2 = new Person('Jack', 16)

console.log(p1.sayHello === p2.sayHello) // => true

缺点:会暴漏很多的函数,容易造成全局变量污染。

原型

原型基本概念

Javascript 规定,每一个函数都有一个 prototype 属性,指向另一个对象。
这个对象的所有属性和方法,都会被构造函数的实例继承。

这也就意味着,我们可以把所有对象实例需要共享的属性和方法直接定义在 prototype 对象上。

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

console.log(Person.prototype)

Person.prototype.type = 'human'

Person.prototype.sayName = function () {
  console.log(this.name)
}

var p1 = new Person(...)
var p2 = new Person(...)

console.log(p1.sayName === p2.sayName) // => true

这时所有实例的 type 属性和 sayName() 方法,其实都是同一个内存地址

构造函数、实例、原型三者之间的关系

构造函数:构造函数就是一个函数,配合new可以新建对象。

实例:通过构造函数实例化出来的对象我们把它叫做构造函数的实例。一个构造函数可以有很多实例。

原型:每一个构造函数都有一个属性prototype,函数的prototype属性值就是原型。通过构造函数创建出来的实例能够直接使用原型上的属性和方法。

思考:内置对象中,有很多的方法,这些方法存在哪里?

__proto__

任意一个对象,都会有__proto__属性,这个属性指向了构造函数的prototype属性,也就是原型对象。

获取原型对象:

  • 通过构造函数.prototype可以获取
  • 通过实例.__proto__可以获取(隐式原型)
  • 它们指向了同一个对象构造函数.prototype === 实例.__proto__

注意:__proto__是浏览器的一个隐藏(私有)属性,IE浏览器不支持,不要通过它来修改原型里的内容,如果要修改原型中的内容,使用构造函数.prototype去修改

constructor属性

默认情况下,原型对象中只包含了一个属性:constructor,constructor属性指向了当前的构造函数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rCbxx1aw-1594804873858)(./media/sanjiao.png)]

原型链

原型链概念

任何一个对象,都有原型对象,原型对象本身又是一个对象,所以原型对象也有自己的原型对象,这样一环扣一环就形成了一个链式结构,我们把这个链式结构称为:原型链。

绘制对象的原型链结构:

//1. var p = new Person();
//2. var o = new Object();
//3. var arr = new Array();
//4. var date = new Date();
//5. Math
//6. 查看一个div的原型链结构

总结:Object.prototype是原型链的尽头,Object.prototype的原型是null。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7g7ko3mD-1594804873860)(media/proto.png)]

属性查找原则

如果是获取操作

  1. 会先在自身上查找,如果没有
  2. 则根据__proto__对应的原型去找,如果没有
  3. 一直找到Object.prototyp,如果没有,那就找不到了。

测试题1

function Person(name) {
  this.name = name
}
Person.prototype.name = 'ls'
Person.prototype.money = 100
var p = new Person('zs')
console.log(p.name)
console.log(p.money)

测试题2

function Person(name) {
  this.name = name
}
Person.prototype.name = 'ls'
Person.prototype.money = 100
var p = new Person()
console.log(p.name)
console.log(p.money)

测试题3

function Person(name) {
  if (name) {
    this.name = name
  }
}
Person.prototype.name = 'ls'
Person.prototype.money = 100
var p = new Person()
console.log(p.name)
console.log(p.money)

属性设置原则

只会修改对象自身的属性,如果自身没有这个属性,那么就会添加这个属性,并不会修改原型中的属性。

function Person() {
  
}

var p = new Person()
Person.prototype.money = 200

console.log(p.money)

p.money = 300

console.log(p.money)

console.log(Person.prototype.money)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值