1、面向对象、判断对象、原型链、this指向

一、面向对象

1、什么是对象?

  • 现实生活中:
    • 世间万物皆对象
  • 编程中:
    • 对单个实物的抽象
    • 对象是一个容器,封装了属性property和方法method
    • 对象是一个集合,包含了数据集和功能集
    • 对象是一个无序属性的集合

2、面向对象

没有属性会报错 没有方法 undefined

  • 是一种编程开发思想。它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟

3、面向对象的特征

封装、继承、多态

二、创建对象的四种方式

1、字面量

var book = {
  price:30,
  name:"JavaScript",
  knowledge:function(){
   console.log(this.name + "赋予我们知识")
 },
}
console.log(book.price)//30
book.knowledge()  //JavaScript赋予我们知识

2、new Object()

var car = new Object()
car.name = "比亚迪";
car.stop = function(){
 console.log(this.name + '可以驻车!')
}
console.log(car)//{name: '比亚迪', stop: ƒ}
car.stop()//比亚迪可以驻车!

3、工厂模式

var createCar = function (color,name,stop) {
  var car = new Object()
  car.color = color;
  car.name = name;
  car.stop = stop;
  return car//必须要返回
}
var c1 = createCar("黑色","奥迪",function () {
  console.log(this.name + "可以在楼下停车")
})
console.log(c1)//{name: '奥迪', color: '黑色', stop: ƒ}
c1.stop()//奥迪可以在楼下停车

4、构造函数

function Person(name,age){
  this.name = name
  this.age = age
  this.study = function() {
	console.log(this.name + "喜欢学习")
 }
}
var p1 = new Person("小花",10)
console.log(p1)//Person {name: '小花', age: 10, study: ƒ}
p1.study()//小花喜欢学习

三、构造函数和实例化对象的关系

1、实例对象是由构造函数new实例化创建出来的

  • 创建一个新对象
  • this指向这个新对象
  • 返回构造函数中的代码
  • 返回新对象
var Cup = function (brand) {
  this.brand = brand
}
var cup = new Cup("Lucky")
console.log(cup);//Cup {brand: 'Lucky'}
console.log(cup.constructor)

image-20240221103254420

2、任何对象都有constructor属性,实例化对象的constructor属性指向构造函数

任何对象的constructor属性都是一个构造函数

  • js中的对象:自定义对象(car/phone)、DOM对象(div/p)、BOM对象(window/console)、内置对象
// 1、自定义对象
var car = new Object()
console.log(car.constructor)//ƒ Object() { [native code] }
// 2、p标签
var pText = document.getElementById('text')
console.log(pText.constructor) //ƒ HTMLParagraphElement()
// 3、浏览器历史记录
console.log(window.history.constructor)//ƒ History() { [native code] }
// window.history = new History()
// 4、日期
console.log(new Date().constructor) //ƒ Date()
// 5、函数
function a() {}
console.log(a.constructor);//ƒ Function() { [native code] }

四、判断对象

obj instanceof Object

  • 如果返回true是对象,返回false不是对象
    false null undefined ‘11.2’ 34都是false
var car = {}
var arr = []
var fn = function () {}
console.log(car instanceof Object)//true
console.log(arr instanceof Object)//true
console.log(fn instanceof Object)//true
console.log(12.4 instanceof Object)//false
console.log('23.4' instanceof Object)//false

五、构造函数内存问题

内存的生命周期

  • 1、内存的开辟
    • 变量的定义:var a
    • 函数声明:function a ( ) { }
  • 2、内存的使用
    • 运算…
    • 变量的操作
    • 函数的调用
  • 3、内存的销毁:JavaScript拥有内存自主回收机制
    • 浏览器关闭
    • 函数调用后:局部的

构造函数内存有存在浪费问题如何解决

1、将公共的属性定义为全局的

//age定义为全局的-----------------------------
var age = 18
var study = function () {
  console.log(this.name+'喜欢学习js')
}
function Person(name,age,sex,study){
  this.name = name
  this.age = age
  this.sex = sex
  this.study = study
}
/*var p1 = new Person('小花', 18, '女生', function () {
    console.log(this.name + '喜欢学习js')
})
console.log(p1)//Person {name: '小花', age: 18, sex: '女生', study: ƒ}
p1.study()//小花喜欢学习js
*/

//年龄改为age-----------------------------
var p1 = new Person('小花', age, sex, study)
var p2 = new Person('小明', age, sex, study)
console.log(p1)//Person {name: '小花', age: 18, sex: '女生', study: ƒ}
console.log(p2)//Person {name: '小明', age: 18, sex: '女生', study: ƒ}
p1.study()//小花喜欢学习js
p2.study()//小明喜欢学习js

2、原型

原型的作用:

1、节省内存空间
2、实现数据共享(继承)

原型、构造函数、实例化对象三者关系
  • 1、任何一个函数都有prototype属性,本身是一个对象
b function fun1() {}
console.log(fn1)   //fn1() {}
console.log(fn1.prototype)

image-20240221144144428

console.log(fn1.prototype instanceof Object)  //true
console.log(typeof fn1.prototype)  //object
  • 2、构造函数也有prototype属性,本身是一个对象,我们称之为原型
function Car(name) {
  this.name = name
}
Car.prototype.color = "白色"
Car.prototype.playMusic = function () {
  console.log("可以播放音乐")
}
var car1 = new Car('比亚迪')
console.log(Car.prototype)

image-20240221144547109

  • 3、原型上的属性和方法都可以被实例化对象所继承 (重点)
    console.log(car1.color) //白色

  • 4、任何一个对象都有constructor属性,实例化对象的constructor属性指向构造函数

var Cup = function (brand) {
   this.brand = brand
}
var cup = new Cup("aaa")
console.log(cup.constructor);

image-20240221184841258

  • 5、原型也是对象也有constructor属性,原型对象的constructor属性指向构造函数
    console.log(Car.prototype.constructor)

image-20240221144803321
console.log(Car.prototype.constructor == Car) //true

  • 6、任何一个对象都有__proto__属性,实例对象的__proto__属性指向构造函数的原型
    console.log(car1.__proto__)

image-20240221144916063
总结:

image-20240221152627237

六、原型链

1、原型链:

  • javascript中每个对象都会有一个__proto__属性,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去__proto__里去找这个属性,这个__proto__又会有自己的__proto__

2、原型链最终指向null

3、实例化对象的属性查找规则:

先从构造函数中查找,有就返回,没有就从原型链上查找,有就返回,没有就返回undefined

构造函数-----原型(undefined)------Object原型

function A() { }
A.prototype.n = 1

var b = new A()

A.prototype = {
    n: 2,
    m: 3
}
var c = new A()
console.log(b.n)//1 
console.log(b.m)//undefined   构造函数原型中没有m
console.log(c.n)// 2 
console.log(c.m)// 3
  • 1、任何一个对象都有__proto__属性,实例对象的__proto__属性指向构造函数的原型
function Cup(brand,capacity) {
  this.brand = brand
  this.capacity = capacity
}
var cup = new Cup('蒙清','200ml')
console.log(cup.capacity)//200ml
console.log(cup.__proto__ === Cup.prototype);//true
//1、任何一个对象都有__proto__属性,实例对象的__proto__属性指向构造函数的原型
console.log(cup.__proto__ === Cup.prototype) //true
  • 2、原型也是对象也有__proto__属性,原型对象的__proto__指向Object构造函数的原型
function Cup(brand) {
  this.brand = brand
}
Cup.prototype.capacity = '800ml'
var cup = new Cup('蒙清')
console.log(cup.capacity)//800ml
//2、原型也是对象也有__proto__属性,原型对象的__proto__指向Object构造函数的原型
console.log(Cup.prototype.__proto__ === Object.prototype) //true
  • 3、Object.prototype也是对象也有__proto__属性,Object.prototype的__proto__指向null
function Cup(brand) {
   this.brand = brand
}
Object.prototype.capacity = '600ml'
var cup = new Cup('蒙清')
console.log(cup.capacity)//600ml
//3、Object.prototype也是对象也有__proto__属性Object.prototype的__proto__指向null
console.log(Object.prototype.__proto__)//null

4、额外的补充:

  • 局部变量转变成全局
function fn1(aa) {
  var num = 67
  aa.num = num
}
fn1(window)
console.log(num)//67

七、改变this指向的方法

相同点:

  • (b.)可以改变this的指向,如果没有参数,this指向window
  • (c.)可以改变this的指向,如果有一个参数,this指向该参数

1、call()

(a.)可以进行函数的调用

var name = '小花'
function fn1() {
  console.log('我是函数声明')
}
fn1()//我是函数声明
fn1.call()//我是函数声明

(b.)可以改变this的指向,如果没有参数,this指向window

var name = "小花"
var obj1 = {
name: '小明',
getName: function () {
 console.log(this.name)
 },
}
obj1.getName.call()//小花

(c.)可以改变this的指向,如果有一个参数,this指向该参数

var name = "小花"
var obj2 = {
name: '小刚',
getName: function () {
 console.log(this.name)
 },
}
obj1.getName.call(obj2)//小刚

(d.)可以改变this的指向,如果有多个参数,this指向第一个参数,剩下的是个参数列表(构造函数继承的案例)

2、apply()

(a.)可以进行函数的调用

(b.)可以改变this的指向,如果没有参数,this指向window

(c.)可以改变this的指向,如果有一个参数,this指向该参数

(d.)可以改变this的指向,如果有多个参数,第一个参数是null或者window,第二个参数是数组

console.log(Math.max(30, 40, 50)) //50
console.log(Math.max.apply(null, [30, 40, 50])) //50
console.log(Math.max.apply(window, [30, 40, 50])) //50

3、bind()

(a.)不可以进行函数的调用

(b.)可以改变this的指向,如果没有参数,this指向window

var name = "小花"
function fn1() {
  console.log('我是函数生命')
}.bind()
fn2()//小花

(c.)可以改变this的指向,如果有一个参数,this指向该参数

var name = '小花'
fn2()//小花
var obj2 = {
  name: '小刚',
  getName: function () {
    console.log(this.name)
  },
}
var obj3 = {
  name: '小丽',
  getName: function () {
    console.log(this.name)
  }.bind(obj2)//小刚
}

八、函数中this指向

如果是实例对象调用,this指向实例化对象

如果是原型对象调用,this指向原型对象

function Cup(name) {
	this.name = name
	this.drink = function () {
  		console.log(this.name + "可以用来喝水")
  }
}
Cup.prototype.name = "我是原型"
var cup = new Cup("小米水杯")
cup.drink()//中的this指向小米水杯
console.log(Cup.prototype.name)//输出我是原型
  • 26
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值