js中面向对象(创建对象的几种方式)
1、面向对象编程(OOP)的特点:
抽象:抓住核心问题
封装:只能通过对象来访问方法
继承:从已有的对象下继承出新的对象
多态:多对象的不同形态
一、创建对象的几种方式
javascript 创建对象简单的来说,无非就是使用内置对象或各种自定义对象,当然还可以使用JSON,但写法有很多,也能混合使用。
1、工厂方式创建对象:面向对象中的封装函数(内置对象)
function createPerson(name){
//1、原料
var obj=new Object();
//2、加工
obj.name=name;
obj.showName=function(){
alert(this.name);
}
//3、出场
return obj;
}
var p1=createPerson('小米');
p1.showName();
与系统对象的区别:
var arr=new Array();//生成一个系统数组对象
1、系统对象是直接用 new 在外面生成,而工厂定义的是在函数内部生成
2、工厂定义的函数名称第一个是小写开头,而系统定义的是大写开头
工厂模式的优缺点:虽然解决了创建相似对象的问题,但是却没有解决对象识别问题(即怎样知道一个对象的类型)。
2、构造函数创建对象
当new去调用一个函数,这个时候函数中的this就是创建出来的对象,而且函数的返回值就是this(隐式返回)
new后面的函数叫做构造函数
<1>有参数的构造函数
function CreatePerson(name){
this.name=name;
this.showName=function(){
alert(this.name);
}
}
var p1=new CreatePerson('小米');
<2>无参数的构造函数
function CreatePerson(){}
var p1=new CreatePerson();
p1.name="小米";
p1.showName=function(){
alert(p1.name);
}
p1.showName();
构造函数模式的优缺点:
1、优点:创建自定义函数意味着将来可以将它的实例标识为一种特定的类型,这是构造函数胜过工厂模式的地方
2、缺点:每个方法都要在每个实例上重新创建一遍
3、对象字面量方式创建对象
person={
name:"小米",
age:23
};
4、用原型方式
1、原型对象:只要创建了一个新函数,就会为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下,所有的原型对象都会自动获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针
2、可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系
function Person(){}
Person.prototype.name="小米";
Person.prototype.showName=function(){
alert(this.name);
}
var p1=new Person();
p1.showName();
原型模式的优缺点:
1、优点:可以让所有的对象实例共享它所包含的属性和方法
2、缺点:原型中是所有属性都是共享的,但是实例一般都是要有自己的单独属性的。所以一般很少单独使用原型模式。
5.混合模型
构造函数模式定义实例属性,而原型模式用于定义方法和共享的属性
function CreatePerson(name){
this.name=name;
}
Create.prototype.showName=function(){
alert(this.name);
}
var p1=new CreatePerson('小米');
p1.showName();
var p2=new CreatePerson('小米');
p2.showName();
alert(p1.showName==p2.showName);//true;原因:都是在原型下面,在内存中只存在一份,地址相同
总结:
function 构造函数(){
this.属性;
}
构造函数.原型.方法=function(){};
var 对象1=new 构造函数();
对象1.方法();
原型:去改写对象下面公用的的方法或属性,让公用的方法或属性在内存中存在一份(提高性能)
原型:prototype:要写在构造函数的下面
var arr=[];
arr.number=10;
Array.prototype.number=20;
alert(arr.number);//10,
//原因:普通定义的要比原型定义的权重大,先会找自身的,自身没有的话再沿着原型链找原型上是否有
属性是否要放在原型下面,就要看该属性是否是可变的,如果不是可变的,就可以放在原型下面,用来公用属性,可变的话放在构造函数下面。
this的指向问题:在事件或者定时器下比较容易出问题
二、包装对象
1、我们把系统自带的对象,叫做系统对象。例如:Array,Date
2、包装对象:基本类型都有自己对应的包装对象:String,Number,Boolean
var str='hello';//基本类型:字符串类型
str.charAt(0);//基本类型会找到对应的包装对象类型,然后包装对象把所有的属性和方法给了基本类型,然后包装对象消失。
str.number=10;//在包装对象下创一个对象,将属性创建在对象下面,然后包装对象就消失了,
alert(str.number);//会弹出undefined;原因:会在包装对象下重新创建一个对象
三、原型链
原型链:实例对象与原型之间的连接,叫做原型链
_proto_(隐式连接)
Object对象类型是原型链的最外层
实例对象->先查找自己本身下面的属性和方法->自身没找到会沿着原型链找到该对象的原型,再查看原型上是否有要查找的属性或方法->依次继续查找如果找到的话则返回,否则找到最顶层Object上还没有就真没有了
四、面向对象中的属性和方法
1、hasOwnProperty():看是否为对象自身下面的属性和方法
只有对象自己定义的属性和方法则返回true,如果在prototype下定义发属性和方法为公用的,所以返回为false;
2、constructor:查看对象的构造函数
(可以用来检测函数类型例如检测是否是数组)
每个原型函数都会自动添加constructor属性(只会生成这一个属性)
for in的时候有些属性是找不到的(系统自带的属性是for in找不到的,自己定义的可以找到)
避免修改constructor属性
function Aaa(){}
//Aaa.prototype.name='小米';
//Aaa.prototype.age=6;
//alert(a1.constructor);//Aaa 原因:只是给原型添加了属性,并不是重新赋值了,自动添加的constructor属性还在。
Aaa.prototype={
// constructor:'Aaa',//需要手动修正指向问题
name:'小米',
age:6
}
var a1=new Aaa();
alert(a1.constructor);//Object 原因:将原型的prototype重新赋值了,但里面没有constructor
注意:以这种方式重设constructor属性会使它的[Enumerable]特性被设置为true,默认情况下,原生的constructor属性是不可枚举的。可以通过Object.defineProperty()来修改。
3、instanceof:运算符
对象与构造函数在原型链上是否有关系,也可以用作类型判断但不是最好的方案,最好的方案是用toString 方法来判断。
4、toString():object上的方法,把对象转化为字符串
var arr=[];
alert(arr.toString==Object.prototype.toString);//false
//原因:系统对象下面都是自带的(例如数组的toString在Array.prototype下),自己写的对象都是通过原型链找到object下面的toString
function Aaa(){}
var a1=new Aaa();
alert(a1.toString==Object.prototype.toString);//true
1>利用toString 进制转化
Number.toString(进制);
var num=255;
alert(num.toString(16));//ff---转化为16进制,默认不写转化为十进制
2>利用toString做类型判断:
//跨页面的情况下上面两种情况会失效
var oF=document.createElement('iframe');
document.body.appendChild('oF');
var ifArray=windows.frames[0].Array;//iframe下的Array数组
var arr=new ifArray();
alert(arr.constructor==Array);//false
alert(arr instanceof Array);//false
alert(Object.prototype.toString.call(arr)=='[object Array]');//true
var arr=[];
alert(Object.prototype.toString.call(arr));//[Object Array]
var arr={};
alert(Object.prototype.toString.call(arr));//[Object Object]
var arr=new Date;
alert(Object.prototype.toString.call(arr));//[Object Date]
var arr=new RegExp;
alert(Object.prototype.toString.call(arr));//[Object RegExp]
var arr=null;
alert(Object.prototype.toString.call(arr));//[Object Null]
五 、继承
1、继承方式:
1、拷贝继承:通用型 有new无new都可以用
2、类式继承:new构造函数---利用构造函数(类)继承的方式
3、原型继承:无new的对象---借助原型来实现对象继承对象
属性继承:调用父类的构造函数call
方法继承:用for in的形式 拷贝继承(jq也用拷贝继承)
var a = {
name: '小米'
};
//拷贝继承
function extend(obj1, obj2) {
for (var attr in obj2) {
obj1[attr] = obj2[attr];
}
}
//原型继承
var b=cloneObj(a);
b.name='小乔';
alert(a.name);
alert(b.name);
function cloneObj(obj) {
var F=function () {};
F.prototype=obj;
return new F();
}
//类式继承
function A() {//父类
this.name='小米';
}
A.prototype.showName=function () {
alert(this.name);
}
function B() {//子类
A.call(this);//属性和方法分开继承
}
//B.prototype=new A();//一句话实现继承,但会有很多问题,比如指向问题,属性会互相影响
//类式继承改进:至少由以下四句实现方法的继承,属性需要分开继承
var F=function () {};
F.prototype=A.prototype;
B.prototype=new F();
B.prototype.constructor=A;//修正指向问题
var b1=new B();
b1.name='笑笑';
b1.showName();
js中面向对象(创建对象的几种方式)的更多相关文章
- JavaScript学习12 JS中定义对象的几种方式【转】
avaScript学习12 JS中定义对象的几种方式 转自: http://www.cnblogs.com/mengdd/p/3697255.html JavaScript中没有类的概念,只有对象. ...
- JavaScript学习12 JS中定义对象的几种方式
JavaScript学习12 JS中定义对象的几种方式 JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工 ...
- JS中事件绑定的三种方式
以下是搜集的在JS中事件绑定的三种方式. 1. HTML onclick attribute <button type="button" id="upl ...
- js中声明Number的五种方式
转载自:http://www.jb51.net/article/34191.htm <!DOCTYPE html> <html> <head> <meta c ...
- JS 面向对象 ~ 创建对象的 9 种方式
一.创建对象的几种方式 1.通过字面量创建 var obj = {}; 这种写法相当于: var obj = new Object(); 缺点:使用同一个接口创建很多单个对象,会产生大量重复代码 2. ...
- 《JS高程》创建对象的7种方式(完整版)
一.理解对象 ECMA-262定义对象:无序属性的集合,其属性可以包含基本值.对象或者属性. 我们可以把 ECMAScript 的对象想象成 散列表:无非就是一组 名值对,其中值可以是数据或函数. 创 ...
- js中实现继承的几种方式
首先我们了解,js中的继承是主要是由原型链实现的.那么什么是原型链呢? 由于每个实例中都有一个指向原型对象的指针,如果一个对象的原型对象,是另一个构造函数的实例,这个对象的原型对象就会指向另一个对象的 ...
- JS中访问对象的两种方式区别
可以使用下面两种方式访问对象的属性和方法 1.对象名.属性名 对象名.方法名() 2.对象名["属性名"] 对象名["方法名"]() var obj = { n ...
- js中定义变量的三种方式const,val,let 的区别
js中三种定义变量的方式const, var, let的区别. 1.const定义的变量不可以修改,而且必须初始化. 1 const b = 2;//正确 2 // const b;//错误,必须初始 ...
随机推荐
- Git学习1:Git起步
本系列文章部分原理和命令相关内容是从 https://git-scm.com/book/zh/v2 摘录,软件实际使用是总结自己的实践经验成文. 1. 关于版本控制 版本控制是一种记录一个或若干文件内 ...
- [Err] 1214 - The used table type doesn't support FULLTEXT indexes
-- -- Table structure for table `film_text` -- -- InnoDB added FULLTEXT support in 5.6.10. If you us ...
- 移动端调试工具weinre
前段时间在大豹公众号上看到一个关于移动端调试的工具,了解了一下,确实不错. npm install -g weinre 先全局安装,然后使用的时候通过如下命令启动 weinre --boundHost ...
- 深入理解linux源码安装三板斧
概述: 根据源码包中 Makefile.in 文件的指示,configure 脚本检查当前的系统环境和配置选项,在当前目录中生成 Makefile 文件(还有其它本文无需关心的文件),然后 make ...
- Linux下实现免密码登录
1.Linux下生成密钥 ssh-keygen的命令手册,通过”man ssh-keygen“命令: 通过命令”ssh-keygen -t rsa“ 生成之后会在用户的根目录生成一个 “.ssh”的文 ...
- [原]C++ double 小数精度控制
第一种方法:cout<<fixed<<setprecision(20)<<mydouble<<endl; #include <iostream&g ...
- C语言 条件编译(if )
#include <stdio.h> #define NUM -1 int main(int argc, const char * argv[]) { #if NUM > 0 pri ...
- 【luogu P3371 单源最短路】 模板 vector+SPFA
stl真是好,,偷懒少写邻接表,, 两个STL应用使代码简短了很多.然而还是那句话,天上不会掉馅饼,程序的效率还是有所下降的.然而,效率不是全部,人们宁可牺牲三倍效率用Java而不用C语言就是最好的例 ...
- Unity3d-制作粒子光环特效
http://blog.csdn.net/ozhangseno/article/details/70799611
- Zabbix: Database Monitor Installation
1. Install ODBC MS SQL Connector On Zabbix Server https://support.zabbix.com/browse/ZBX-6839 ...