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面向对象,原型,继承的更多相关文章

  1. JS面向对象组件 -- 继承的其他方式(类式继承、原型继承)

    继承的其他形式: •类式继承:利用构造函数(类)继承的方式 •原型继承:借助原型来实现对象继承对象   类 : JS是没有类的概念的 , 把JS中的构造函数看做的类 要做属性和方法继承的时候,要分开继 ...

  2. JS 面向对象之继承 -- 原型链

    ECMAScript只支持实现继承,其实现继承主要是靠原型链来实现. 原型链的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 简单回顾下构造函数.原型和实例的关系: 每个构造函数都有 ...

  3. js面向对象之继承-原型继承

    //animal 父类 超类 var Animal = function(name) { this.name = name; this.sayhello = function() { alert(&q ...

  4. js面向对象-原型链

    var Person = function (name) { this.name = name; } Person.prototype.say = function () { console.log( ...

  5. Node.js的原型继承函数util.inherits

    util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数.JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同.Jav ...

  6. Node.js的原型继承函数 util.inherits

    转自:http://sentsin.com/web/179.html util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数.Java ...

  7. js的原型继承小结

    考虑:有一个想要复用的对象,并且想要创建的第二个对象需要从第一个对对象中获取其功能. 实现如下: //要继承的对象 var parent = { name:"Papa" }; // ...

  8. js面向对象之继承那点事儿根本就不是事

    继承 说道这个继承,了解object-oriented的朋友都知道,大多oo语言都有两种,一种是接口继承(只继承方法签名):一种是实现继承(继承实际的方法) 奈何js中没有签名,因而只有实现继承,而且 ...

  9. 捋一捋js面向对象的继承问题

    说到面向对象这个破玩意,曾经一度我都处于很懵逼的状态,那么面向对象究竟是什么呢?其实说白了,所谓面向对象,就是基于类这个概念,来实现封装.继承和多态的一种编程思想罢了.今天我们就来说一下这其中继承的问 ...

  10. JS——面向对象、继承

    创建对象的方式: 1)单体 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...

随机推荐

  1. 一百零三、SAP中常量的定义CONSTANTS

    一.代码如下 二.运行效果如下

  2. vue 父子传值,子页面没有实时刷新的问题

    在做高德地图的时候,发现列表点击编辑的时候,地图不能实时更新: <el-form-item label="门店坐标:" :label-width="formLabe ...

  3. SpringBoot的Banner横幅

    SpringBoot的Banner横幅即在SpringBoot应用程序启动过程中,日志输出的如下内容: 如果想替换此部分内容的话,可以在classpath根路径下建立一个文件,命名为:banner.t ...

  4. windows LARGE_INTEGER 错误码输出格式

    如果是负数,I32X 版权声明:本文为博主原创文章,未经博主允许不得转载.

  5. BZOJ 3876 [Ahoi2014&Jsoi2014]支线剧情

    题解: 带下界的费用流 对于x->y边权为z Addedge(x,t,1,0) Addedge(s,y,1,z) Addedge(x,y,inf,0) 然后对每个点Addedge(i,1,inf ...

  6. Mac Go 环境变量配置

    GOPATH 是工作目录,就是你打代码,代码的存放目录 GOROOT 是Go的安装目录,我下载的是免安装版的 现在的Go环境变量就是设置成这个样子, 终于Bee不会报错了!!!

  7. qt 程序发布打包

    1. 首先把 release 版本的 exe 复制到其他文件夹,比如 Desktop\test 2. 使用开始菜单中 qt 里面的控制台窗口,使用 cd 命令打开到 Desktop\test 位置,然 ...

  8. RGB转到HSV色彩空间转换

    原文链接:https://blog.csdn.net/lsg19920625/article/details/78416649

  9. 吴裕雄--天生自然 JAVASCRIPT开发学习:字符串

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  10. 2020PHP面试-网络篇

    一.网络协议分层 OSI七层: 物理层.数据链路层.网络层.传输层.会话层.表示层.应用层. TCP/IP四(五)层 : 物理层(主要是光电信号的传输). 数据链路层(MAC地址.以太网协议).网络层 ...