创建对象
工厂模式
通过创建函数调用函数来创建对象
function createBottle(name,price,isKeepWarm){
return{
name: name,
price: price,
isKeepWarm: isKeepWarm
};
}
var bottle = createBottle('太空杯',49,false);
var bottle2 = createBottle('bottle',49,true);
var bottle3 = createBottle('bottle',59,true);
函数
属性:name\length\prototype
方法:bind()\call()\apply()
arguments\this
函数的arguments
function createBottle(name,price,isKeepWarm){
return{
name: name,
price: price,
isKeepWarm: isKeepWarm
};
}
可以写成
function createBottle(){
return{
name: arguments[0],
price: arguments[1],
isKeepWarm: arguments[2]
};
}
- 是个对象,类数组,length属性
- 不要滥用,会影响程序的可读性
- 非常适合动态函数的场景
函数的this
执行环境
看作用域,作用域不同,this所代表的值也不同。
函数的方法
- bind()
改变函数的this指向 - call()
改变函数的this,传参可以直接传 - apply()
改变函数的this,传参以数组的形式
函数的属性
- name
- length
声明的时候确定的参数length- arguments.length
调用的时候传入的参数length
- arguments.length
- prototype
对象,实现继承的重要属性
函数是first class
数据类型
First Class 可以作为函数的参数和返回值,也可以赋给变量
Second Class 可以作为函数的参数,但不能从函数返回,也不能赋给变量
Third Class 不能作为函数的参数
var add = function(a,b){
return a + b;
};
var add = new Function('a','b','return a + b;');
闭包
闭包是指有权访问另一个函数作用域中的变量的函数
function foo(){
var a = 'test';
function bar(){
return a;
}
retrun bar;
}
var bar = foo();
bar();
私有变量和特权方法
私有变量:
- 任何在函数中定义的变量,都可以认为是私有变量。因为不能在函数外部访问这些变量。
- 私有变量包括函数参数,局部变量以及在函数内部定义的其他函数。
特权方法:
有权访问私有变量和私有函数的公有方法
在函数的内部创建一个闭包,那么闭包通过自己的作用域链也可以访问这些私有变量
构造函数
instanceof 是实例
var bottle = new Bottle(‘杯子’,59,true);
console.log(bottle instanceof Bottle);
构造函数:
- 没有显示的创建对象
- 将属性和方法赋值给this
- 没有return语句
(使用new)
构造函数的不足之处
功能相同的函数,重复声明消耗空间
原型prototype
原型是函数的一个属性,是一个对象
如果函数作为构造函数使用,那么这个构造函数的所有实例,都共享这个原型对象
- constructor
指向构造函数 - 读写
解决构造函数的浪费内存问题 - isPrototypeOf
检测实例是不是挂了原型
共享的缺陷
数据污染
完美地创建对象--构造函数结合原型
1.构造函数独享属性
2.原型共享方法
- 属性的覆盖
实例属性会覆盖原型中的属性 - 属性的判断
- in操作符
判断对象里有没有某个属性 - hasOwnProperty
判断属性是挂在实例上而不是原型上
- in操作符
继承
原型链
- 打通原型链
Children.prototype = new Parents();
PS:原型链的不足
-
constructor 指向问题
手动指向原型链
Children.prototype = new Parents();
Children.prototype.constructor = Children; -
属性共享问题
数据污染 -
参数
参数固定,不能传递参数
借用构造函数继承
function Parents(color){
this.color = color;
}
function Children(color){
Parents.call(this,color);
}
组合继承
- 属性和方法都是从父类继承的(代码复用)
- 继承的属性是私有的(互不影响)
- 继承的方法都在原型里(函数复用)
PS:组合继承的不足
1.重复调用,浪费
2.属性冗余
最佳实践
inheritPrototype(subType,superType){
var protoType = Object.create(superType.prototype);//复制父类的原型
protoType.constructor = subType;//重置constructor
subType.prototype = protoType;//修改子类原型
}
继承属性
继承方法
ES6创建类用class
ES6继承通过extends
class Student extends Person {
// 构造函数
constructor(name, grade) {
super(name);
this.grade = grade;
}
// 方法
sayGrade() {
console.log(`I am Grade ${this.grade}`);
}
}
p(HTMLParagraphElement)\div(HTMLDivElement)\input(HTMLInputElement)
---------继承自---------->HTMLElement
---------继承自---------->Element
---------继承自---------->Node