Commit 28780e24 authored by zhangfangli's avatar zhangfangli

构造函数和普通函数

parent 22524797
Pipeline #17573 failed with stage
---
title: 构造函数和普通函数
author: 张芳利
date: 2023-1-30
---
<a name="auZns"></a>
## 构造函数
是一种特殊的函数,主要用来初始化对象的,也就是为对象成员变量赋初始值。特提供模板,描述对象的基本结构。就像平时我们把对象中一些公共属性和方法抽取出来,然后封装到这个函数里面。要与关键字**new** 一起使用。
1. 构造函数用于创建某一类对象,首字母大写
2. 与 new 一起使用
3. 执行构造函数里面的代码,给这个新对象添加属性和方法
4. 内部用 **this** 来构造属性和方法
5. 返回这个对象
**new:** new 申请内存,创建对象,当调用new 时,后台会隐时执行**new Object()。**所以通过new创建的字符串、数字是引用类型。
```javascript
// 构造函数
function Person(name, age){
this.name = name
this.age = age
this.say = function(){
console.log(this.naame+'say hai');
}
}
const ming = new Person('ming', 18)
console.log(ming);
// 检查mimg是否是Person的实例
console.log(ming instanceof Person);// true
// 检查ming是否是Object的实例
console.log(ming instanceof Object);// true
```
从最后一行代码中看出ming 其实就是一个对象。
<a name="dTLvP"></a>
### 构造函数原型
构造函数通过原型分配的函数是所有对象共享的。<br />每一个构造函数都有一个**prototype**属性,指向另一个对象。这个对象的属性和方法,都会被构造函数拥有。我们可以把那些不变的方法,直接定义在prototype对象上,这样所有的对象的实例就可以共享这些方法了。<br />对象都会有一个属性**_proto_**指向构造函数的**prototype**属性和方法**。**
就像我们上面写的,把say 写在构造函数中,会造成**内存浪费**<br />![image.png](/yifu-study-front-share/images/function/构造函数和普通函数1.png)<br />使用**prototype实现共享**
```javascript
// 使用prototype 实现共享
Person.prototype.sayFun = function(){
console.log(this.name+'say hai');
}
const p1 = new Person('张三', 18)
console.log(Person.prototype === p1.__proto__);// true
```
**_proto_**对象原型和原型对象**prototype**是等价的
<a name="ObUUB"></a>
### constructor
对象原型**_proto_和**原型对象**prototype**里都有一个**constructor**属性,称为构造函数,指的是构造函数本身。
```javascript
console.log(Person.prototype.constructor);
console.log(p1.__proto__.constructor);
ƒ Person(name, age){
this.name = name
this.age = age
}
```
很多情况下,我们如果修改了冤魂来的原型队形,给原型独享赋值的是一个对象,需要手动利用**constructo**这个属性指会原来的构造函数;
```javascript
Person.prototype = {
sayFun: function(){
console.log(this.name+'say hai');
},
doFun:function(){
console.log(this.name+'do hai');
}
}
console.log(Person.prototype.constructor);
console.log(p1.__proto__.constructor);
```
![image.png](/yifu-study-front-share/images/function/构造函数和普通函数2.png)
```javascript
Person.prototype = {
constructor: Person,// 修复constructor指向 重写了原型对象,constructor指向Object
sayFun: function(){
console.log(this.name+'say hai');
},
doFun:function(){
console.log(this.name+'do hai');
}
}
```
![image.png](/yifu-study-front-share/images/function/构造函数和普通函数3.png)<br />** 扩展内置对象的时候用 Array.prototype.xxx = function () {},不要用Array.prototype={},会覆盖。
<a name="PT19q"></a>
### this
1. 构造函数中,this指向的是对象实例
2. 原型对象函数里面的this指向的也是对象实例
> 1. 普通函数调用 this指向window
> 2. 对象方法调用 this指向对象
> 3. 构造函数调用 this指向实例对象
> 4. call apply bind改变this指向
> 5. 箭头函数没有this指向,this指向上一级作用域的this
```javascript
// 普通函数
function fn1(){
console.log(this); // window
}
// 对象调用
const obj = {
name: 'obj',
fn2: function(){
console.log(this); // obj
}
}
// 箭头函数
const obj2 = {
name: 'obj2',
fn3: () => {
console.log(this); // window 箭头函数没有this指向,this指向上一级作用域的this
}
}
// 构造函数
function Fn4(name){
this.name = name
console.log(this); // Fn4 {name: 'fn4'}
}
const fn4 = new Fn4('fn4')
// call apply bind
function fn5(){
console.log(this); // {name: 'fn5'}
}
const obj3 = {
name: 'fn5'
}
fn5.call(obj3)
```
<a name="WKLU8"></a>
### ES6中class与构造函数的关系
class 为构造函数的语法糖,也就是class的本质是构造函数。class的继承**extends**本质是构造函数的原型链的继承。
```javascript
class People{
constructor(name, age){ // 构造函数 用来初始化实例 new的时候会执行
this.name = name
this.age = age
}
say(){
console.log('say hi');
}
}
const p = new People('张三', 18)
console.log(p);
p.say()
function People1(name, age){
this.name = name
this.age = age
}
People1.prototype.say = function(){
console.log('say hi');
}
const p1 = new People1('李四', 20)
console.log(p1);
p1.say()
```
通过class 定义的类和通过构造甘薯定义的类,二者本质相同。js 在执行的时候,会把class转为构造甘薯执行。所以ES6 class的写法本质就是构造函数。
<a name="SeeP6"></a>
## 普通函数
普通函数就是直接调用,默认情况下,你没有return,返回的就是undefined。
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment