JS面向对象,原型,继承
ECMAScript有两种开发模式:1.函数式(过程化),2.面向对象(OOP)。面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。但是,ECMAScript没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。
var box = new Object();
box.name = 'Lee';
box.age = 100;
box.run = function()
{
return this.name + this.age + '运行中...'; //this表示当前作用域下的对象,即new Object()实例化出来的那个对象,this要放在一个作用域下。比如box.run(){}。
}
alert(box.run());
alert(this.name); //这里的this 代表window
工厂模式 解决了重复实例化的问题,但是无法识别对象
function createObject(name,age)
{
var obj = new Object(); //创建对象
obj.name = name; //添加属性
obj.age = age;
obj.run = function(){
return this.name + this.age + '运行中...';
};
return obj; //返回对象引用
}
var box1 = createObject('Lee',100);
var box2 = createObject('Jack',200);
alert(box1.run());
alert(box2.run());
alert(typeof box1);
alert(typeof box2);
构造函数创建对象
function Box(name,age){ //创建一个对象,所有构造函数的对象其实就是Object
this.name = name; //添加一个属性
this.age = age;
this.run = function(){ //添加一个方法
return this.name + this.age + '运行中...';
};
};
function Desk(name,age){ //创建一个对象,所有构造函数的对象其实就是Object
this.name = name; //添加一个属性
this.age = age;
this.run = function(){ //添加一个方法
return this.name + this.age + '运行中...';
};
};
//1.构造函数没有new Object,但它后台会自动var obj = new Object
//2.this就相当于obj
//3.构造函数不需要返回对象引用,它是后台自动返回的
//1.构造函数也是函数,但函数名第一个字母大写
//2.必须new构造函数名();new Box(),而这个Box第一个字母也是大写的。
//3.必须使用new运算符。
var box1 = new Box('Lee',100);
var box2 = new Box('Jack',200);
var box3 = new Desk('kkk',500);
alert(box1.run());
alert(box2.run());
alert(box1 instanceof Box);
alert(box2 instanceof Box);
alert(box3 instanceof Desk);
原型
function Box(){} //构造函数函数体内什么都没有,这里如果有,叫做实例属性,实例方法
Box.prototype.name = 'Lee'; //原型属性
Box.prototype.age = 100; //原型属性
Box.prototype.run = function(){ //原型方法
return this.name + this.age + '运行中...';
};
var box1 = new Box();
var box2 = new Box();
alert(box1.name);
alert(box1.run());
//如果是实例方法,不同的实例化,它们的方法地址是不一样的,是唯一的。
//如果是原型方法,那么它们的地址是共享的。
//alert(box1.run == box2.run); //地址共享,因为box1和box2的run方法都属于Box的原型方法
//alert(box1.prototype); //这个属性是一个对象,访问不到
//alert(box1.__proto__); //这个属性是一个指针指向prototype原型对象,IE浏览器不支持这个属性,打印不出来
//alert(box1.constructor); //构造属性,可以获取构造函数本身。作用是被原型指针定位,然后得到构造函数本身。其实就是对象实例对应的原型对象的作用。
//判断一个对象实例(对象引用)是不是指向了原型对象,基本上,只要实例化,他自动指向的。
//alert(Box.prototype.isPrototypeOf(box1));
//var obj = new Object();
//alert(Object.prototype.isPrototypeOf(obj));
//原型模式的执行流程
//1.先查找构造函数实例里的属性或方法,如果有,立刻返回;
//2.如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回。
//box1.name = 'Jack'; //实例属性,并没有重写原型属性,就近原则
//alert(box1.name);
//alert(box2.name); //实例属性不会共享,所以box2访问不到实例属性,只能访问原型属性
//delete box1.name; //删除实例中的属性
//delete Box.prototype.name; //删除原型中的属性
//Box.prototype.name = 'KK'; //覆盖原型中的属性
//alert(box1.name);
//box1.name = 'KAC'
//alert(box1.hasOwnProperty('name')); //判断实例中是否存在指定属性
//alert('name' in box1); //不管实例属性或者原型属性是否存在,只要有就返回true
//判断只有原型中存在属性
//function isProperty(object,property){
//return !object.hasOwnProperty(property) && (property in object)
//}
//alert(isProperty(box1,'name'));
function Box(){};
var box = new Box();
alert(box.prototype); //使用对象实例无法访问到prototype
alert(box.__proto__); //使用对象实例访问prototype的指针
alert(Box.prototype); //使用构造函数名(对象名)访问prototype
//使用字面量的方式创建原型对象
function Box(){};
//这里{}就是对象,是Object,new Object就相当于{}
Box.prototype = {
constructor:Box, //强制指向Box
name:'Lee',
age:100,
run:function(){
return this.name + this.age + '运行中...';
}
};
//使用字面量的方式创建的原型对象会导致constructor指向Object而不是Box
字面量方式创建原型对象的constructor之所以会指向Object是因为Box.prototype={};
这种写法其实就是创建了一个新对象。而每创建一个函数,就会同时创建它的prototype,
这个对象也会自动获取constructor属性。所以,新对象的constructor重写了Box原来的constructor
因此会指向新对象,而新对象没有指定构造函数,那么就是指向Object。
//重写了原型对象
Box.prototype = {
age:200; //这里不会保留之前原型的任何信息了。把原来的原型对象和构造函数对象实例之前的关系切断了。
}
var box = new Box();
//alert(box.constructor == Box);
alert(box.age);
//数组排序
var box = [5,1,6,9,3,5,8,1];
alert(box.sort());
//查看sort是否是Array原型对象里的方法
alert(Array.prototype.sort);
//查看substring是否是String原型对象里的方法
alert(String.prototype.substring);
//内置引用类型的功能扩展
String.prototype.addstring = function(){
return this + ',被添加了!';
};
var box = 'Lee';
alert(box.addstring());
//原型缺点
function Box(){}
Box.prototype={
constructor:Box,
name:'Lee',
age:100,
family:['gege','jiejie','meimei'],
run:function(){
return this.name + this.age + '运行中...'
}
};
var box1 = new Box();
alert(box1.family);
box1.family.push('didi'); //在第一个实例修改后引用类型,保持了共享
alert(box1.family);
var box2 = new Box();
alert(box2.family); //共享了box1添加后的引用类型的原型
//为了解决构造传参和共享问题,可以组合构造函数+原型模式
function Box(name,age){
this.name = name;
this.age = age;
this.family = ['gege','jiejie','meimei'];
}
Box.prototype = {
constructor:Box,
run:function(){
return this.name + this.age + '运行中...';
}
};
var box1 = new Box('Kee',100);
alert(box1.family);
box1.family.push('didi');
alert(box1.family);
var box2 = new Box('lee',200);
alert(box2.family); //引用类型没有使用原型,所以没有共享
//动态原型模式,可以将原型封装到构造函数里。封装性更好
function Box(name,age){
this.name = name;
this.age = age;
this.family = ['gege','jiejie','meimei'];
if(typeof this.run != 'function'){ //判断this.run是否存在
//alert('KS')
Box.prototype.run = function(){
return this.name + this.age + '运行中...';
};
//alert('JS');
}
}
//原型的初始化,只要第一次初始化就可以了,没必要每次构造函数实例化的时候都初始化
var box1 = new Box('Kee',100);
var box2 = new Box('lee',200);
//寄生构造函数 工厂模式+构造函数
function Box(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name + this.age + '运行中...';
};
return obj;
}
var box1 = new Box('Lee',100);
alert(box1.run());
var box2 = new Box('Jack',200);
alert(box2.run());
//稳妥构造函数
function Box(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name + this.age + '运行中...';
};
return obj;
}
var box1 = Box('Lee',100);
alert(box1.run());
var box2 = Box('Jack',200);
alert(box2.run());
//继承,通过原型链实现
function Box(){ //被继承的函数叫做超类型(父类,基类)
this.name = 'Lee';
}
Box.prototype.name = 'Jack';
function Desk(){ //继承的函数叫做子类型(子类,派生类)
this.age = 100;
}
function Table(){
this.level = 'AAAAAA';
}
//通过原型链继承,超类型实例化后的对象实例,赋值给予类型的原型属性
//new Box()会将Box构造里的信息和原型里的信息都交给Desk
//Desk的原型,得到的是Box的构造+原型里的信息
Desk.prototype = new Box(); //通过原型链继承
Table.prototype = new Desk();
var desk = new Desk();
var table = new Table();
alert(desk.age);
alert(desk.name); //就近原则,实例里有,就返回,没有就去原型查找
alert(table.level);
//子类型从属于自己或者其他的超类型
alert(desk instanceof Desk);
alert(desk instanceof Box);
alert(box instanceof Desk);
//使用对象冒充继承
function Box(name,age){
this.name = name;
this.age = age;
this.family = ['GEGE','JIEJIE','MEIMEI']; //引用类型,放在构造里就不会被共享
}
Box.prototype.family = 'jiating';
function Desk(name,age){
Box.call(this,name,age) //对象冒充,只能继承构造里的信息
}
var desk = new Desk('Lee',100);
alert(desk.name);
alert(desk.family);
//原型链+借用构造函数的模式,这种模式称为组合继承,解决了复用的问题
function Box(name,age){
this.name = name;
this.age = age;
this.family = ['GEGE','JIEJIE','MEIMEI'];
}
Box.prototype.run = function(){
return this.name + this.age + '运行中...';
}
//构造函数里的方法,放在构造函数里,每次实例化,都会分配一个内存地址,浪费空间.最好放在原型里,保证多次实例化只有一个地址
function Desk(name,age){
Box.call(this,name,age) //对象冒充
}
Desk.prototype = new Box(); //原型链继承
var desk = new Desk('Lee',100);
alert(desk.run());
//原型式继承:这种继承借助原型并基于已有的对象创建新对象,同时还不会因此创建自定义类型。
//临时中转函数
function obj(o){ //o表示将要传递进入的一个对象
function F(){} //F构造是一个临时新建的对象,用来存储传递过来的对象
F.prototype = o; //将o对象实例赋值给F构造的原型对象
return new F(); //最后返回这个得到传递过来对象的对象实例
}
//F.prototype = 0其实就相当于Desk.prototype = new Box();
//这是字面量的声明方式,相当于var box = new Box();
var box = {
name:'Lee',
age:100,
family:['gege','jiejie','meimei']
};
//box1就等于new F();
var box1 = obj(box);
//alert(box1.name);
alert(box1.family);
box1.family.push('didi');
alert(box1.family);
var box2 = obj(box);
alert(box2.family); //引用类型的属性共享了
//寄生式继承 = 原型式+工厂模式
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
//寄生函数
function create(o){
var f = obj(o);
f.run = function(){
return this.name + '方法';
}
return f;
}
var box = {
name:'Lee',
age:100,
family:['gege','jiejie','meimei']
};
var box1 = create(box);
alert(box1.run());
//寄生组合继承
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
//寄生函数
function create(box,desk){
var f = obj(box.prototype);
f.constructor = desk; //调整原型构造指针
desk.prototype = f;
}
function Box(name,age){
this.name = name;
this.age = age;
}
Box.prototype.run = function(){
return this.name + this.age + 'ssssss';
}
function Desk(name,age){
Box.call(this,name,age); //对象冒充
}
//通过寄生组合继承来实现继承
create(Box,Desk); //这个用来替代Desk.prototype = new Box();
var desk = new Desk('Lee',100);
alert(desk.run());
alert(desk.constructor);
JS面向对象,原型,继承的更多相关文章
- JS面向对象组件 -- 继承的其他方式(类式继承、原型继承)
继承的其他形式: •类式继承:利用构造函数(类)继承的方式 •原型继承:借助原型来实现对象继承对象 类 : JS是没有类的概念的 , 把JS中的构造函数看做的类 要做属性和方法继承的时候,要分开继 ...
- JS 面向对象之继承 -- 原型链
ECMAScript只支持实现继承,其实现继承主要是靠原型链来实现. 原型链的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 简单回顾下构造函数.原型和实例的关系: 每个构造函数都有 ...
- js面向对象之继承-原型继承
//animal 父类 超类 var Animal = function(name) { this.name = name; this.sayhello = function() { alert(&q ...
- js面向对象-原型链
var Person = function (name) { this.name = name; } Person.prototype.say = function () { console.log( ...
- Node.js的原型继承函数util.inherits
util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数.JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同.Jav ...
- Node.js的原型继承函数 util.inherits
转自:http://sentsin.com/web/179.html util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数.Java ...
- js的原型继承小结
考虑:有一个想要复用的对象,并且想要创建的第二个对象需要从第一个对对象中获取其功能. 实现如下: //要继承的对象 var parent = { name:"Papa" }; // ...
- js面向对象之继承那点事儿根本就不是事
继承 说道这个继承,了解object-oriented的朋友都知道,大多oo语言都有两种,一种是接口继承(只继承方法签名):一种是实现继承(继承实际的方法) 奈何js中没有签名,因而只有实现继承,而且 ...
- 捋一捋js面向对象的继承问题
说到面向对象这个破玩意,曾经一度我都处于很懵逼的状态,那么面向对象究竟是什么呢?其实说白了,所谓面向对象,就是基于类这个概念,来实现封装.继承和多态的一种编程思想罢了.今天我们就来说一下这其中继承的问 ...
- JS——面向对象、继承
创建对象的方式: 1)单体 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...
随机推荐
- 如何通过模仿提升Paper写作能力?
对于大部分初到国外留学的中国留学生们来说要想自己独立完成一篇Paper可能难度会很大,从Paper字体字号要求.Paper写作格式.Paper写作结构等等诸多因素都会影响留学生们写Paper的效率.对 ...
- Intent 显示意图 隐式意图
//显式意图 :必须指定要激活的组件的完整包名和类名 (应用程序之间耦合在一起) // 一般激活自己应用的组件的时候 采用显示意图 //隐式意图: 只需要指定要动作和数据就可以 ( 好处应用程序之 ...
- JVM源码分析之自定义类加载器如何拉长YGC
概述 本文重点讲述毕玄大师在其公众号上发的一个GC问题一个jstack/jmap等不能用的case,对于毕大师那篇文章,题目上没有提到GC的那个问题,不过进入到文章里可以看到,既然文章提到了jstac ...
- C++ STD Gems03
transform.for_each #include <iostream> #include <vector> #include <string> #includ ...
- Pandas_one-hot encoding与dummy encoding
Pandas_特征编码 one-hot encoding 基本思想是将离散型特征的每一种取值都看成一种状态,保证每一个取值只会使得一种状态处于激活状态. 编码函数pd.get_dummies() du ...
- MAT工具在MacBook的安装
当Java应用出现内存溢出的问题的时候,需要拿工具分析dump文件的.JDK自带的jvisualvm和jhat都可以使用,另外还有一个工具是 Memory Analyzer Tool ,支持独立运行和 ...
- 吴裕雄--天生自然Django框架开发笔记:Django 模板
使用 django.http.HttpResponse() 来输出 "Hello World!".该方式将数据与视图混合在一起,不符合 Django 的 MVC 思想. Djang ...
- Hive鲜为人知的宝石-Hooks
本来想祝大家节日快乐,哎,无奈浪尖还在写文章.谴责一下,那些今天不学习的人.对于今天入星球的人,今天调低了一点价格.减少了20大洋.机不可失失不再来.点击阅读原文或者扫底部二维码. hive概述 Hi ...
- halcoN GPU
halcon18.11——DL http://www.ihalcon.com/read-11150.html 楼主# 更多发布于:2018-12-04 19:50 1. 按顺序下载安装 h ...
- 【动手学pytorch】pytorch的基础操作
一.Tensor a) 张量是torch的基础数据类型 b) 张量的核心是坐标的改变不会改变自身性质. c) 0阶张量为标量(只有数值,没有方向的量),因为它不随 ...