简介:不少概念不清或忘记,从新构建本身的知识体系。天天问本身1~多个问题。我是菜鸟 成为大神之路!
html
①语法结构建立的对象使用{},[]数组
var o = {name: "Lis",sex:16}; | o 这个对象继承了Object.prototype上面的全部属性
|
var arr = ["yo", "whadup", "?"]; | 数组都继承于 Array.prototype (Array.prototype 中包含 indexOf, forEach等方法)
|
function fun(){ | 函数都继承于Function.prototype (Function.prototype 中包含 call, bind等方法)
return 2; |
} |
复制代码
②构造器建立的对象使用new
在 JavaScript 中,构造器其实就是一个普通的函数。当使用 new 操做符 来做用这个函数时,它就能够被称为构造方法(构造函数)bash
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v){
this.vertices.push(v);
}
};
var obj = new Graph();
obj是生成的对象,他的自身属性有'vertices'和'edges'.
在obj被实例化时,obj.[[Prototype]]指向了Graph.prototype.
复制代码
③Object.create 建立的对象>>link
ECMAScript 5
中引入了一个新方法。新对象的原型就是调用 create
方法时传入的第一个参数。app
④class 关键字建立的对象
ECMAScript6
引入了一套新的关键字用来实现 class
。使用基于类语言的开发人员会对这些结构感到熟悉,但它们是不一样的。JavaScript
仍然基于原型。这些新的关键字包括 class, constructor,static,extends 和 super
。ide
"use strict";
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
class Square extends Polygon {
constructor(sideLength) {
super(sideLength, sideLength);
}
get area() {
return this.height * this.width;
}
set sideLength(newLength) {
this.height = newLength;
this.width = newLength;
}
}
var square = new Square(2);
复制代码
// 定义一个交通工具类
function Vehicle() {
// 属性
this.name;
this.number;
// 实例方法
this.funBase = function(){
console.log("交通工具名称:"+this.name+"||"+"可乘坐人数:"+this.number);
}
}
// 原型方法
Vehicle.prototype.funRatio = function(ratio) {
console.log(this.name + ':' + ratio);
};
复制代码
核心: 将父类的实例做为子类的原型函数
function Car(){
this.getName = function(){
console.log(this.name);
return this.name;
}
};
function Airplane(){
this.getName = function(){
console.log(this.name);
return this.name;
}
};
Car.prototype = new Vehicle();
Car.prototype.name = '汽车';
Car.prototype.number = '20人';
Airplane.prototype = new Vehicle();
Airplane.prototype.name = '飞机';
Airplane.prototype.number = '100人';
var car = new Car();
var airplane = new Airplane();
//测试
car.funBase();
car.funRatio("60%");
car.getName();
airplane.funBase();
airplane.funRatio("36%");
airplane.getName();
console.log(car instanceof Vehicle); // true
console.log(car instanceof Car); //true
复制代码
执行结果: 工具
特色:
* 很是纯粹的继承关系,实例是子类的实例,也是父类的实例
* 父类新增原型方法/原型属性,子类都能访问到
* 简单,易于实现
缺点:
* 要想为子类新增属性和方法,必需要在new Animal()这样的语句以后执行,不能放到构造器中
* 没法实现多继承
* 来自原型对象的全部属性被全部实例共享(来自原型对象的引用属性是全部实例共享的)(详细请看附录代码: 示例1)
* 建立子类实例时,没法向父类构造函数传参
'推荐指数:★★(三、4两大体命缺陷)'
复制代码
核心:使用父类的构造函数来加强子类实例,等因而复制父类的实例属性给子类(没用到原型)性能
function Car(){
Vehicle.call(this);
this.name = '汽车';
this.number = '20人';
this.getName = function(){
console.log(this.name);
return this.name;
}
}
// 测试
var car = new Car();
car.funBase();
car.funRatio("60%");//TypeError: car.funRatio is not a function[详细了解]
car.getName();
console.log(car instanceof Vehicle); // false
console.log(car instanceof Car); //true
复制代码
执行结果 测试
特色:
* 解决了1中,子类实例共享父类引用属性的问题
* 建立子类实例时,能够向父类传递参数
* 能够实现多继承(call多个父类对象)
缺点:
* 实例并非父类的实例,只是子类的实例
* 只能继承父类的实例属性和方法,不能继承原型属性/方法
* 没法实现函数复用,每一个子类都有父类实例函数的副本,影响性能
'推荐指数:★★(缺点3)'
复制代码
核心:为父类实例添加新特性,做为子类实例返回ui
function Car(){
var vehicle = new Vehicle();
vehicle.name = '汽车';
vehicle.number = '20人';
vehicle.getName = function(){
console.log(vehicle.name);
return vehicle.name;
}
return vehicle;
}
// 测试
var car = new Car();
car.funBase();
car.funRatio("60%");//TypeError: car.funRatio is not a function[详细了解]
car.getName();
console.log(car instanceof Vehicle); // true
console.log(car instanceof Car); //false
复制代码
执行结果:
特色:
* 不限制调用方式,无论是new 子类()仍是子类(),返回的对象具备相同的效果
缺点:
* 实例是父类的实例,不是子类的实例
* 不支持多继承
'推荐指数:★★'
复制代码
核心:逐一复制父类实例的属性方法给子类实例
function Car(){
var vehicle = new Vehicle();
for(var p in vehicle){
Car.prototype[p] = vehicle[p];
}
this.getName = function(){
console.log(this.name);
return this.name;
}
}
// 测试
Car.prototype.name = '汽车';
Car.prototype.number = '20人';
var car = new Car();
car.funBase();
car.funRatio("60%");
car.getName();
console.log(car instanceof Vehicle); //false
console.log(car instanceof Car); //true
复制代码
执行结果:
特色:
* 支持多继承
缺点:
* 效率较低,内存占用高(由于要拷贝父类的属性)
* 没法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)
'推荐指数:★(缺点1)'
复制代码
核心:经过调用父类构造,继承父类的属性并保留传参的优势,而后经过将父类实例做为子类原型,实现函数复用
function Car(){
Vehicle.call(this);
this.name = '汽车';
this.number = '20人';
this.getName = function(){
console.log(this.name);
return this.name;
}
}
Car.prototype = new Vehicle();
Car.prototype.constructor = Car;//组合继承也是须要修复构造函数指向
// 测试
var car = new Car();
car.funBase();
car.funRatio("60%");
car.getName();
console.log(car instanceof Vehicle); // true
console.log(car instanceof Car); //true
复制代码
执行结果:
特色:
* 弥补了方式2的缺陷,能够继承实例属性/方法,也能够继承原型属性/方法
* 既是子类的实例,也是父类的实例
* 不存在引用属性共享问题
* 可传参
* 函数可复用
缺点:
* 调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)
'推荐指数:★★★★(仅仅多消耗了一点内存)'
复制代码
核心:经过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
function Car(){
Vehicle.call(this);
this.name = '汽车';
this.number = '20人';
this.getName = function(){
console.log(this.name);
return this.name;
}
}
(function(){
// 建立一个没有实例方法的类
var Super = function(){};
//设置原型
Super.prototype = Vehicle.prototype;
//将实例做为子类的原型
Car.prototype = new Super();
// 须要修复下构造函数
Car.prototype.constructor = Car;
})();
// 测试
var car = new Car();
car.funBase();
car.funRatio("60%");
car.getName();
console.log(car instanceof Vehicle); // true
console.log(car instanceof Car); //true
复制代码
执行结果:
特色:
* 堪称完美
缺点:
* 实现较为复杂
'推荐指数:★★★★(实现复杂,扣掉一颗星)'
复制代码
(相关apply()、bind()方法的使用)
①call()、apply()、bind() 都是用来重定义 this 这个对象的!
②参数:
* call的参数是直接放进去的,第二第三第n个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,'成都', ... ,'string' );
* apply的全部参数都必须放在一个数组里面传进去 obj.myFun.apply(db,['成都', ..., 'string' ]);
*
③方法:
* apply:调用一个对象的一个方法,用另外一个对象替换当前对象。例如:B.apply(A, arguments);即A对象'应用'B对象的方法。
* call:调用一个对象的一个方法,用另外一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象'调用'B对象的方法。
复制代码
参考文章:
① www.cnblogs.com/humin/p/455…
② www.cnblogs.com/lengyuehuah…