1.构造函数
1.1 对象
1.2 类
1.3 构造函数
1.3.1 实例
1.3.2 构造函数的缺点
同一个构造函数的多个实例之间,无法共享属性,从而造成对系统资源的浪费。
/* 公有的属性或者公有的方法我们可以放在原型对象上 */
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype.eat = "水果"
var p = new Person("li",19)
var zhang = new Person("zhang",20)
console.log(p);
console.log(zhang);
1.3.3 构造函数
构造函数:构造一个类(对象)的函数
构造函数的特点:
1.首字母大写
2.函数内部使用this关键字,谁new(实例化)就指向谁
3.使用this关键字给对象添加属性
4.必须使用new关键字,去生成一个对象
// 在 javascript 中新建一个类 使用构造函数
function Student(name,age){
this.name = name;
this.age=age
}
/* this 指实例化的对象 */
/* 实例 */
var zheng = new Student("zcy",18)
console.log(zheng);
// 读取对象的属性
console.log(p.name);
console.log(p.age);
1.3.4 instanceof 判断一个对象是不是某个类的实例
var arr = [1,2,3]
console.log(arr instanceof Array); // true
function Person(name,age){
this.name = name
this.age = age
}
var p = new Person("zheng",18)
console.log(p instanceof Person); // true
2.原型
2.1 原型
# JS的继承是基于原型的继承
/* 原型
1.obj.__proto__ 找到它的原型对象
2.数组上的方法都是挂载在原型上(Array.prototype)的
*/
// toString() 因为数组的原型上有字符串toString()
// push,unshift() 因为数组原型上有
var arr = [1,2,3]
console.log(Array.prototype);
console.log(arr.__proto__);
console.log(arr.__proto__ == Array.prototype);
2.2 原型对象作用
# 原型对象:是某一类对象的基类,所有创建的对象都会共享该原型对象 (共享机制)
# 作用:将对象通用的方法挂载在原型上
var arr = [1,2,3]
Array.prototype.sum = function(params){
if(Array.isArray(params)){
return params.reduce((a,b)=>a+b)
}
}
console.log(arr.sum(arr));
Array.prototype.http = function(){
console.log("http");
}
arr.http()
function Teacher(name,age){
this.name = name
this.age = age
}
/* sayName */
Teacher.prototype.sayName = function(){
console.log(this.name);
}
var p = new Teacher("lisi",30)
console.log(p);
3.原型链
var arr = [1,2,3]
console.log(arr.__proto__);
console.log(arr.__proto__ == Array.prototype);
console.log(arr.__proto__.__proto__)
console.log(arr.__proto__.__proto__ == Object.prototype)
console.log(arr.valueOf());
4、构造属性
4.1 构造属性
## 创建构造函数的时候,原型对象上会有一个constructor属性,它是原型对象所独有的,它指回构造函数本身
function Person(name,age){
this.name = name
this.age = age
}
var p = new Person("cheng",20)
console.log(p.constructor);
console.log(p.constructor == Person); // true
var arr = [1,2,3]
console.log(arr.constructor == Array); // true
4.2 给原型添加属性 ( 直接量形式 )
# 问题:我们以直接量(对象)形式,给原型添加属性的时候,它的constructor会指向Object
# 解决:重置 constructor
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype = {
sayName:function(){
console.log(this.name);
},
sayAge(){
console.log(this.age);
}
}
var p = new Person("cheng",20)
console.log(p.constructor); //Object
console.log(p.constructor == Person); // false
console.log(p instanceof Person); // true
## 解决办法
Person.prototype = {
constructor:Person, // 重置 constructor
sayName:function(){
console.log(this.name);
},
sayAge(){
console.log(this.age);
}
}
var p = new Person("cheng",20)
console.log(p.constructor); // Person
console.log(p.constructor == Person); // true
4.3 公有属性和私有属性
# 公有属性: 一般在原型对象上
# 私有属性: 通过this关键字去添加的
# hasOwnProperty: 可以判断属性是私有的还是公有的
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype = {
constructor:Person,
sayName:function(){
console.log(this.name);
},
sayAge(){
console.log(this.age);
}
}
var p = new Person("cheng",20)
console.log(p.hasOwnProperty("name")); // true 私有的
console.log(p.hasOwnProperty("sayName")); // false 公有的
//判断constructor是否是原型对象的私有属性
console.log(Person.prototype.hasOwnProperty("constructor")); // true
5.函数内部this指向
5.1 函数中this指向
函数正常调用的时候this指向: window
定时器: window
构造函数:实例化对象
var name = "张三"
function show(){
console.log(this.name);
}
function go(){
var name = "李四"
show()
}
go() // "张三" // window.go()
function go(){
var name = "李四"
console.log(this.name); // window.name
}
go() // "张三" window.go()
5.2 改变函数中this指向
5.2.1 call
语法: funName.call(obj,arg1,arg2...)
var name="王五"
var obj = { name:"李四" }
function go(){
console.log(this.name);
}
go() // 王五
go.call(obj) // 李四
5.2.2 apply
语法:funName.call(obj,[arg1,arg2...])
call,apply的区别:
应用场景:传递多个参数的情况
call依次去传递
apply 需要传递数组
var name="window"
var zhang={
name:"张三"
}
function show(a,b){
console.log(this.name);
console.log(a+b);
}
show(1,2)
show.call(zhang,2,3)
show.apply(zhang,[1,2])
5.2.3 bind
bind 绑定的函数不会马上执行,只是改变了函数上下文的执行环境
call,apply调用的时候马上执行
var name = "window"
var zhang = {
name:"张三"
}
var show = function (a,b){
console.log(this.name);
console.log(a+b);
}.bind(zhang)
show(2,3) // zhang 5
5.2.4 使用场景
- 解决定时器中this的指向问题 ```javascript
解决
1.使用bind解决
btn.onclick = function(){
setTimeout(function(){
console.log(this.id);
}.bind(btn),1000)
}
/* btn.onclick = function(){
var self = this
setTimeout(function(){
console.log(this.id);
}.bind(self),1000)
}
btn.onclick = function(){
setTimeout(function(){
console.log(this.id);
}.bind(this),1000)
}
*/
2.使用箭头函数解决
btn.onclick = function(){ setTimeout(()=>{ console.log(this.id); },1000) }
<a name="MezJv"></a>
## 6.继承
<a name="Wh51z"></a>
## Javascript的继承是基于原型的继承
<a name="m6q9m"></a>
### 6.1 属性的继承
```javascript
# call 实现属性的继承
function Person(name,age){
this.name = name;
this.age = age
}
function Teacher(name,age,skill){
Person.call(this,name,age) // Person(name,age)中的this指向window,需要改变this指向
this.skill = skill // this指向 Teacher构造函数的实例对象
}
var t = new Teacher("zhang",18,"js")
console.log(t);
6.2 方法的继承
function Person(name,age){
this.name = name;
this.age = age
}
Person.prototype.sayName = function(){
console.log(this.name);
}
function Teacher(name,age,skill){
Person.call(this,name,age)
this.skill = skill
}
Teacher.prototype = Person.prototype
Teacher.prototype.constructor = Teacher
Teacher.prototype.sayAge = function(){
console.log(this.age);
}
var t = new Teacher("zhang",18,"js")
console.log(t);
t.sayName()
t.sayAge()
6.2.1 es5中实现继承的方法
function Person(name,age){
this.name = name;
this.age = age
}
Person.prototype.sayName = function(){
console.log(this.name);
}
function Teacher(name,age,skill){
Person.call(this,name,age)
this.skill = skill
}
Teacher.prototype = Object.create(Person.prototype,{
constructor:{
value:Teacher
}
})
Teacher.prototype.sayAge = function(){
console.log(this.age);
}
var t = new Teacher("zhang",18,"js")
console.log(t);
console.log(t.constructor);
t.sayName()
t.sayAge()