【重学JS】-5,this和构造函数

134 阅读3分钟

这是我参与2022首次更文挑战的第2天,活动详情查看:链接

一,什么是this?

浏览器在调用函数时,每次都会向函数内部传递一个隐含参数,就是 this , this指向是一个对象。

这个对象我们称它为函数执行的上下文对象,根据函数调用方式不同,this会指向不同的对象。

function fun(a,b){
  console.log(this.name)
}

var obj = {
	name:'张三',
  sayName: fun
}
 
obj.sayName == fun ?? //true

我们可以这样去判断this的指向

  1. 以函数形式调用,this永远都是window
  2. 以方法形式调用,this就是调用方法的对象(如上例子代码,调用obj.sayName,得到的this为该对象)
  1. 当以构造函数形式调用,this就是新创建的那个对象。

二,看个例子

var name = '全局的'

function fun(){
	console.log(this.name)
}

var obj = {
	name:'张三',
  age:19,
  sayName:fun
}

var obj2 = {
	name:'李四',
  age:12,
  sayName:fun
}

console.log(obj.sayName())

console.log(obj2.sayName())

结果

\

三,工厂模式创造对象

使用工厂模式创建对象,通过该方法生成大批量对象

function createPerson(name,age,gender){
	var obj = new Object()
  obj.name = name
  obj.age = age 
  obj.gender = gender
  return obj
}

var obj = createPerson('张三',19,'男')

使用工厂模式创建的对象,使用的构造函数都是 Object , 所以创建的对象都是object类型,可以通过打印查看。

控制台会打印 #[Object,Object]

这样会导致我们无法区别出多种不同的类型。

四,构造函数

什么是构造函数?像 new Object(), new Array() ... 等 JavaScript为我们提供的构造函数,创建一个构造函数,与创建普通函数无任何差别,不同的是

构造函数习惯首字母大写 ,调用方式不同:普通函数直接调用,而构造函数需要使用new关键字来调用

function Person(name,age,gender){
	this.name = name
  this.age = age
  this.gender = gender
  this.sayName = function(){
 		console.log('我是:'+ this.name)
  }
}

var per = new Person('张三',12,'男')

可以看到,使用构造函数创建的对象,constructor 是这个构造函数本身。

控制台打印 #[Person,Object]


#构造函数执行的流程

  1. 立刻创建一个新的对象
  2. 将新建的对象设置为函数this,在构造函数中使用
  1. 执行函数中的代码,this来引用新建的对象
  2. 将新建的对象作为返回值返回

使用同一个构造函数创建的对象,我们称为类对象,也将一个构造函数称为一个类。

我们将通过一个构造哈函数创建的对象,称为该类的实例。

#使用instanceof 检查一个对象是否是某个类的实例

语法:对象 instanceof 构造函数

如:
console.log(per instanceof Person) //true
console.log(per instanceof Object) //true

所有的对象都是Object的后代,所以使用instanceof 检查对象和object时,都会返回true。

五,外部创建构造函数的方法

在上面的Person构造函数中,为每个对象都添加一个sayName方法,目前,我们的方法都是在构造函数内部创建的,也就是说,构造函数每执行一次就会新创建一个新的sayName 方法。

也就是所有的实例的方法都是唯一的。

这样就会导致够着函数每执行一次,就会创建对应新的方法,也就是构造函数内部方法都会重新创建。这是完全没有必要的,完全可以使所有的对象共同调用一个方法,如:

//将sayName 方法在全局作用域中定义
function sayName(){
	alert('我是:'+ this.name)
}

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

但有个问题,在全局中定义了函数,会污染全局作用域命名空间。而且定义在全局作用域中也很不安全。

下一章我们讲解通过在原型上定义去处理这一问题。