构造函数
定义:通过 new 函数名来实例化对象的函数叫构造函数。任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数的主要 功能为 初始化对象,特点是和new 一起使用。new就是在创建对象,从无到有,构造函数就是在为初始化的对象添加属性和方法。构造函数定义时首字母大写(规范)。
工厂函数创建对象
function person(name,age,hobby,gender){
const obj = {}
obj.name = name
obj.age = age
obj.hobby = hobby
obj.gender = gender
return obj
}
const p1 = person("Tom",15,"basketball","男")
const p2 = person("Cendy",14,"valleball","女")
自定义构造函数的创建
- 构造函数必须和
new
连用new Date()
new Array()
- 和
new
连用的作用- 1、把一个普通函数变成构造函数 能够有创建对象的功能
- 让这个函数的内部的
this
指向这个创建出来的对象,这个创建出来的对象 叫做实例化对象
function person(name,age,gender){
//this => 实例化对象
this.name = name
this.age = age
this.gender = gender
}
const p1 = new person("Tom",13,"男") //person 函数内部的 this => 指向 p1
const p2 = new person("Cendy",13,"女") //person 函数内部的 this => 指向 p2
构造函数的使用
为了区分普通函数和构造函数,我们一般将构造函数的名字的首字母大写
function Person(){
this.name = "Tom"
}
const p1 = new Person
const p2 = new Person()
构造函数的使用注意:
- 1、必须和
new
连用- 创建一个对象
- 让这个函数内部的 this 指向 实例化对象
- 2、和
new
连用的时候,不管有没有参数,都还是把括号写上
构造函数的一个案例:
function Person(name,age){
this.name = name
this.age
//this => 实例化对象
this.sayHi = () =>{
console.log(this)//指向 `Person`
console.log(this.name + "年龄" + this.age)
}
}
const p1 = new Person("Ton",15) //p1 是一个对象 this.sayHi = p1.sayHi = function(){} 开辟了一块空间 把这个空间的地址给了 p1.sayHi
const p1 = new Person("BOb",15)//p2 是一个对象 this.sayHi = p1.sayHi = function(){} 开辟了一块空间 把这个空间的地址给了 p1.sayHi
console.log(p1.sayHi === p2.sayHi) //false
原型对象
- 每一个函数都有一个自带的成员 叫做 prototype 这个prototype 是一个对象空间
- 既然这个prototype 是一个对象,那就可以往这个对象里面添加内容
- 一般把属性直接写在函数体内,把方法写在
prototype
里面
function Person(name.age){
this.name = name
this.age = age
}
Person.prototype.sayHi = function(){
console.log(this.name)
}
const p1 = new Person("Tom",15)
const p2 = new Person("Bon",16)
p1.sayHi() //Tom
p2.sayHi() //Bon
console.log(p1.sayHi() === p2.sayHi()) //true
原型属性
每一个对象天生自带一个属性 叫做_proto_
它的指向是所有构造函数(由谁创建出来)的 prototype
functiion Person(name,age){
this.name = name
this.age.age
}
Person.prototype.sayHi = function(){
}
const p1 = new Person("Tom",25)
const p2 = new Person("Bon",19)
//p1 是一个对象,所以也有 __proto__ 这个属性
console.log(p1.__proto__ === Person.prototype) //true
对象的访问规则
- 找对象身上的一个属性的时候,如果在对象自己的身上找不到 就去到
__proto__
里面__proto__
指向的又是所属构造函数的prototype
- 因为
prototype
也是对象,所以他也有__proto__
这个属性
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype.gender = "男"
const p1 = new Person("Tom",15)
const p2 = new Person("Bon",16)
console.log(p1.gender)
//p1.gender => p1.__proto__.gender === Person.prototype.gender
原型链
- 每一个没有明确所属构造函数的 { } 他的所属构造函数都是 Object
- 原型链就是由
__proto__
组成的链状结构 终点就是Object.prototype
如果再往上就是null
function Fn( ){
this.name = "Fn"
}
console f1 = new Fn()
console f2 = new Fn()
console.log(f1.sayHi)
/**
* 会先在自己身上找,自己找不到就去 f1.__proto__(Fn.prototype) 里面找,如果
* f1.__proto__(Fn.prototype) 也找不到,那就继续往上找, 找到
* Fn.prototype.__proto__(Object.prorotype) 找到了就返回 找不到就返回undefined
*/
console.log(f1.__proto__.__proto__ === Object.prototype)//true
判断Fn.prorotype.__proto__
所属构造函数是不是Object
console.log(Fn.prototype.__proto__ === Object.prototype)
constructor 出厂证明
function Fn(){
this.name = "Fn"
}
console.log(Fn.constructor)//Function
const arr = [1,2,3]
console.log(arr.constructor)//Array
//判断属性
console.log(Fn.constructor === Function) //true
面向对象思想
function Tab(){}
Tab.prototype.函数名 = function(){
}
this指向问题
- this 不是一个变量,所以和作用域访问和赋值规则都没有关系
- this 是一个关键字 其他得变量名不能是this
- 只有全局作用域和局部作用域有 this 这个东西
- 只要是全局作用域下,那么所有的this都指向 window
//局部作用域
function fn(){
//这是 fn 的私有作用域
console.log(this)
}
var fun = function(){
//这是 fun 的私有作用域
console.log(this)
}
fn()
fun()
//只要是函数名() 调用 那么函数内部的this 都指向 window
//我们看this指向什么的时候,不要看函数在哪定义,只要看他怎么调用
只有作用域 才有 this 关键字 他不是一个变量 所以和作用域的访问和赋值规则没有关系
this 指向的问题
不要管函数在哪儿定义 只看他怎么调用
1、函数名() this => window
2、***.函数名() this => .前面那个东西
3、事件处理函数中 this => 事件源(由谁触发的这个事件)
4、全局作用域 this => window