面向对象编程
实例对象与new关键字
- js的面向对象通过constructor和原型prototype实现的
- 构造函数
- 内部使用
this关键字,代表创建实例 - 生成对象时必须使用
new关键字
- 内部使用
new原理步骤- 创建一个空对象,作为返回的对象
- 将空对象原型指向构造函数的
prototype属性 - 将这个空对象赋值给函数内部的
this - 执行构造函数内部代码
- 构造函数内部
return只能返回对象,如果写的是return 5,则不论是什么基本类型,都会返回this指向的对象 - 构造函数
return一个对象,则返回这个对象,不返回this指向的对象(强调上一条) new.target这个属性只有用new关键字时才会有值,可以以此来判断是否使用了new- 防止忘记写
new去发生错误,可以使用new.target简化省去new
function Person(name,age){
if(!new.target){
return new Person(name,age)
}
this._name = name
this._age = age
}
p1 = Person('forkeep',22)
p2 = new Person('hz',20)
console.log(p1._name)//forkeep
console.log(p2._name)//hz
Object.create创建实例对象
var person1 = {
name:'lz',
age:22,
hello:function(){
console.log('Hi! '+this.name)
}
}
var person2 = Object.create(person1)
console.log(person2.age)//22
person2.hello()//Hi! lz
this关键字
-
它总返回一个对象
-
this就是属性、方法当前所在的对象 -
尤其注意函数的定义时刻和触发时刻是截然不同的
-
this的指向会变 -
实质:对象名存着对象所在内存的地址,函数名存着函数所在内存的地址
-
this使用场景:全局window,构造函数,对象的方法 -
一定要注意
-
避免多层
this -
避免数组处理中使用
this -
避免回调函数中使用
this
-
-
绑定
thisFunction.prototype.call(this[,arg1.,arg2..])括号里的第一个参数thisFunction.prototype.apply(this[,[arg1,arg2...]])括号里的第一个参数是thisFunction.prototype.bing(this,[,arg1,arg2...])返回一个函数,绑定this不变,也可以绑定参数不变,按顺序绑定
对象继承
-
通过原型链实现继承功能
-
不使用继承缺点:相同属性,函数重复声明定义,占用内存空间
-
原型链继承思想:相同属性、函数定义在构造函数的原型上
-
实例中有相同的属性、方法,则不去寻找原型中的该属性、方法
-
原型链
-
构造函数
Person,Person.prototype.constructor === Person //true -
Person实例p,p.constructor === P.prototype.constructor -
constructor属性可以知道一个实例是哪个构造函数创建的 -
constructor可以通过一个实例创建另一个实例,不需要知道是哪个构造函数(原因见上一条) -
修改原型时,注意不要把
constructor无意之间修改了 -
最好不要直接给
Person.prototype赋值,而是使用Person.prototype.method = function(){} -
instanceof对象是否是一个构造函数的实例v instanceof Vehicle // 等同于 Vehicle.prototype.isPrototypeOf(v) -
instanceof检查整个原型链 -
构造函数的继承
-
在子类构造函数中调用父类构造函数
-
子类原型指向父类原型(采用
Object.create())//第一步 function Sub(value) { Super.call(this); this.prop = value; } //第二步 Sub.prototype = Object.create(Super.prototype); Sub.prototype.constructor = Sub; Sub.prototype.method = '...';
-
-
多重继承(
Object.assign())function M1() { this.hello = 'hello'; } function M2() { this.world = 'world'; } function S() { M1.call(this); M2.call(this); } // 继承 M1 S.prototype = Object.create(M1.prototype); // 继承链上加入 M2 Object.assign(S.prototype, M2.prototype); // 指定构造函数 S.prototype.constructor = S; var s = new S(); s.hello // 'hello' s.world // 'world' -
模块化方法(封装到一个对象中
new Object({}))var module1 = new Object({  _count : 0,  m1 : function (){   //...  },  m2 : function (){  //...  } });-
缺点:
_count属性暴露在外边可以被随意修改 -
封装私有变量
- 构造函数写法(利用闭包)
- 缺点:
buffer变量一直占用内存
- 缺点:
function StringBuilder() { var buffer = []; this.add = function (str) { buffer.push(str); }; this.toString = function () { return buffer.join(''); }; }-
立即执行函数写法 IIFE(实际用到的写法)
var module1 = (function () {  var _count = 0;  var m1 = function () {   //...  };  var m2 = function () {   //...  };  return {   m1 : m1,   m2 : m2  }; })(); -
优化的立即执行函数写法
(function($, window, document) { function go(num) { } function handleEvents() { } function initialize() { } function dieCarouselDie() { } //attach to the global scope window.finalCarousel = { init : initialize, destroy : dieCarouselDie } })( jQuery, window, document );说明:
finalCarousel对象对外暴露init,detory方法,内部方法外部无法调用。- 其他方法外部无法访问
- 后边括号传的参数,前边括号声明形参
- 构造函数写法(利用闭包)
-