1.构造函数
1.1 对象
1.2 类
1.3 构造函数
1.3.1 实例
1.3.2 构造函数的缺点
同一个构造函数的多个实例之间,无法共享属性,从而造成对系统资源的浪费。
/* 公有的属性或者公有的方法我们可以放在原型对象上 */function Person(name,age){this.name = namethis.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); // truefunction Person(name,age){this.name = namethis.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 = namethis.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 = namethis.age = age}var p = new Person("cheng",20)console.log(p.constructor);console.log(p.constructor == Person); // truevar arr = [1,2,3]console.log(arr.constructor == Array); // true
4.2 给原型添加属性 ( 直接量形式 )
# 问题:我们以直接量(对象)形式,给原型添加属性的时候,它的constructor会指向Object# 解决:重置 constructor
function Person(name,age){this.name = namethis.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); //Objectconsole.log(p.constructor == Person); // falseconsole.log(p instanceof Person); // true## 解决办法Person.prototype = {constructor:Person, // 重置 constructorsayName:function(){console.log(this.name);},sayAge(){console.log(this.age);}}var p = new Person("cheng",20)console.log(p.constructor); // Personconsole.log(p.constructor == Person); // true
4.3 公有属性和私有属性
# 公有属性: 一般在原型对象上# 私有属性: 通过this关键字去添加的# hasOwnProperty: 可以判断属性是私有的还是公有的
function Person(name,age){this.name = namethis.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.prototypeTeacher.prototype.constructor = TeacherTeacher.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()
