JavaScript对象创建,继承
创建对象
在JS中创建对象有很多方式,第一种:
var obj = new Object();
第二种方式:
var obj1 = {};//对象直面量
第三种方式:工厂模式
function Person(){
var obj = new Object();
obj.name = 'xxx';
obj.age = 12;
return obj;
}
var p1 = Person();
typeof p1 ;// object
第四种方式:构造函数模式
var Person = function(name,age,job){
this.name = name;//赋值
this.age = age;
this.job = job;
this.sayName = function(){
return this.name;
}
};
通过构造函数的模式,需要经历四个步骤:
1:创建一个新的空对象
2:将构造函数的作用域赋给到空对象(this指向这个空对象)
3:执行构造函数中的代码(为这个对象添加属性)
4:返回这个对象
var person1 = new Person('xx',12,'engineer');
var person2 = new Person('xxwy',12,'teacher');
第五种方式,ES5实现,这种方式其实也是对象中的继承。
var obj2 = Object.createObject(obj1);
构造函数
var Person = function(name){
this.name = name;
}
//new 操作符
var p1 = new Person('xxx');
p1.name ; //xxx
//普通函数调用
Person('sssss');
window.name ;//sssss this指向window 在非严格模式下
//call,apply方式调用
var obj = {};
Person.call(obj,'dddddddddd');
obj.name ;//dddddddd
var person1 = new Person('wfx',12,'engineer');
var person2 = new Person('wy',12,'teacher');
//这两个对象都有constructor(构造函数)属性
console.log(person1.constructor === Person); //true
console.log(person2.constructor === Person); //true
不过一般通过instanceof来判断实例对象是否属于该构造函数
console.log(person1 instanceof Person); //true
console.log(person2 instanceof Person); //true
构造函数和普通函数在JS中并没有任何区别,唯一的区别在于他们调用的方式不同。构造函数通过new 操作符调用。
var Person = function(name){
this.name = name;
};
//构造函数new 操作符
var p1 = new Person('x');
p1.name ;//x
//普通函数调用
Person('d');
window.name ;//d 在非严格模式下 浏览器全局对象是window this指向window
//call apply方式调用
var obj = new Object();
Person.call(obj,'ddd');
obj.name; //ddd
构造函数存在的问题:
//因为JS中函数是对象,新建函数时,创建新的函数不是同一个函数的实例
//即使同一个构造函数中同一个方法是不同的对象实例,但是方法又是完成一致。存在浪费内存
console.log(person1.sayName === person2.sayName);//false
改进方式:
1、创建全局函数,这个方式存在问题是,需要创建大量全局函数,没有封装性。
var Cat = function(name){
this.name = name;
//this.sayName = function(){
// return this.name;
//}
this.sayName = sayName;
};
function sayName(){
return this.name;
}
2、通过原型
首先我们认识原型,在每个函数创建的时候,就会通过一些系列规则给每个函数生成一个prototype属性,这个属性是一个指针,指向一个对象即原型对象(function.prototype)。给这个原型对象上添加属性或者方法可以让每个实例对象共享原型对象上的属性和方法。原型对象中会有一个constructor属性指向这个对象的函数(即原本函数)。
var Dog = function(){};
Dog.prototype.name = 'dog';//共享属性
Dog.prototype.sayName = function(){return this.name};//共享方法
var dog1 = new Dog();
var dog2 = new Dog();
console.log(dog1.sayName === dog2.sayName);//true
JS中有两个方法来判断 对象跟其原型对象的关系的方法:
1、isPrototypeof() 判断一个原型对象是否是该实例对象的原型对象
var Person = function(){
this.name = 'wfx';
};
//Person.prototype.constructor == Person; true
Person.prototype.name = 'wfx';
Person.prototype.age = 12;
Person.prototype.sayName = function(){
return this.name;
};
var person1 = new Person();
var person2 = new Person();
console.log(Person.prototype.isPrototypeOf(person1));//true
console.log(Person.prototype.isPrototypeOf(person2));//true
2、Object.getPrototypeOf(obj) 获得obj原型对象
console.log(Object.getPrototypeOf(person1)===Person.prototype);//true
console.log(Object.getPrototypeOf(person2));//Person.prototype console.log(person1.name);//'wfx'
理解原型对象:
先看图

以前我们说过,创建函数的时候会自动生成prototype属性,该属性指向一个对象。在上图就是Person.prototype(原型对象),该原型对象中会自动生成一个constructor属性,该属性指向该构造函数即Person
每个实例对象中会带有一个内部属性[[prototype]],该属性会指向原型对象。

给原型对象添加一个name属性,一个sayName方法。
这是,person1实例对象会共享这个属性和方法,同时也会共享constructor属性。
1 person1.name;//张三
2 person1.sayName();//张三
3 person1.constructor;//Person
这里我们给person1实例对象添加一个name属性、
person1.name = '王麻子‘;
我们改变了person1对象的name属性。但是并没改变person2的name属性。
person2.name;//’张三‘
person1.name ;//'王麻子’
我们可以理解实例对象会首先查找自身是否带有该属性或者方法如果有限调用自身的属性或方法,没有的话在通过原型链(下面再说)查找原型对象是否有该属性或方法,有则调用没有则继续通过原型链查找上一级原型对象,以此类推,直至Object对象。
判断一个属性是否是实例对象自身的属性可以通过hasOwnProperty();
person1.name = 'ddddd';
person1.hasOwnProperty('name');//true;
判断一个属性是否是在实例对象属性中可以通过in 操作符;
name in person2 ;//true
枚举对象属性使用for in
for-in返回一个对象可以访问的属性
Object.keys(obj);返回一个对象可以枚举且是实例自身属性。
Object.getOwnPropertyNames(obj);返回对象所有的属性。
原型对象的问题
由于是共享,导致在引用数据类型共享
var Person = function(){
}
Person.prototype.firends = [1,23,4,4];
var p1 = new Person();
p1.firends;//[1,23,4,4];
p2.firends;//[1.23,4,4];
//修改p1.firends
p1.firends = ['a'];
//同时p2也被修改了。
p2.firends ;//['a']
所以才用混合模式
//属性在构造函数中
var Person = function(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.firends = [1,2,3,4,5];
}
//方法在原型对象中
Person.prototype = {
constructor : Person,
sayName : function(){return this.name},
sayAge : function(){return this.age}
}
继承
JS中的继承比较特别,因为JS没有真正的类这个说法,我们可以仿照经典类继承。我们还可以利用原型链实现继承,也可以同时使用经典继承和原型链继承。在ES5中有Object.create();继承的方式。
1:经典继承
经典继承利用是函数的call,apply方法,改变this的指向。
var Person = function(name){
this.name = name;
}
var Man = function(name,sex){
Person.call(this,name);
this.sex = sex;
}
2:原型链继承
var Person = function(name){
this.name = name;
}
var Man = function(name,sex){
// Person.call(this,name);
this.sex = sex;
}
Perosn.prototype = {
constructor:Person;
syaHi : function(){
return this.name;
}
};
Man.prototype = new Person();
3:混合模式继承
混合模式下也存在一些缺点,两次利用了构造函数。
var Person = function(name){
this.name = name;
}
var Man = function(name,sex){
Person.call(this,name);//第一次
this.sex = sex;
}
Perosn.prototype = {
constructor:Person;
syaHi : function(){
return this.name;
}
};
Man.prototype = new Person();//第二次
4:改进继承
var Person = function(name){
this.name = name;
}
var Man = function(name,sex){
Person.call(this,name);//第一次
this.sex = sex;
}
Perosn.prototype = {
constructor:Person;
syaHi : function(){
return this.name;
}
};
//extend函数
function extend(sub,sup){
//参考JS高级程序
var F = function(){};//创建一个空函数,在利用原型链的时候不在使用父类的构造函数
F.prototype = sup.prototype;
sub.prototype = new F(); //实现原型继承
sub.prototype.constructor = sub;
sub.superClass = sup.prototype;.//方便调用父类的原型的方法
}
extend(Man,Person);
JavaScript对象创建,继承的更多相关文章
- #JavaScript对象与继承
JavaScript对象与继承 JavaScript是我在C语言之后接触的第二门编程语言,大一暑假的时候在图书馆找了一本中国人写的JavaScript程序设计来看.那个时候在编程方面几乎还是小白,再加 ...
- JavaScript对象的继承
原文 简书原文:https://www.jianshu.com/p/78ce11762f39 大纲 前言 1.原型链继承 2.借用构造函数实现继承 3.组合模式继承 4.原型式继承 5.寄生式继承 6 ...
- javascript对象创建及继承
//****************************************************************************** //创建类的多种方式 //------ ...
- JavaScript大杂烩4 - 理解JavaScript对象的继承机制
JavaScript是单根的完全面向对象的语言 JavaScript是单根的面向对象语言,它只有单一的根Object,所有的其他对象都是直接或者间接的从Object对象继承.而在JavaScript的 ...
- JavaScript 对象创建
tips: JavaScript 除了null和undefined之外,其他变量都可以当做对象使用. JavaScript 的基本数据类型有:number boolean string null u ...
- 【JavaScript学习】JavaScript对象创建
1.最简单的方法,创建一个对象,然后添加属性 var person = new Object(); person.age = 23; person.name = "David"; ...
- 深入JavaScript对象创建的细节
最近深入学习javascript后,有个体会:面向对象的方式编程才是高效灵活的编程,也是现在唯一可以让代码更加健壮的编程方式.如果我们抛开那些玄乎的抽象出类等等思想,我自己对面向对象的从写程序的角度理 ...
- JavaScript对象创建的几种方式
1 工厂模式 1.1 创建 function createFruit(name,colors) { var o = new Object(); o.name = name; o.colors = co ...
- Javascript 对象创建多种方式 原型链
一.对象创建 1.new Object 方式 直接赋上属性和方法 var obj = new Object(); obj.name = '娃娃'; obj.showName = function(){ ...
随机推荐
- .NET WebAPI 用ExceptionFilterAttribute实现错误(异常)日志的记录(log4net做写库操作)
好吧,还是那个社区APP,非管理系统,用户行为日志感觉不是很必要的,但是,错误日志咱还是得记录则个.总不能上线后报bug了让自己手足无措吧,虽然不管有木有错误日志报bug都是件很头疼的事... 我们知 ...
- MVC跨域CORS扩展
一般的基于浏览器跨域的主要解决方法有这么几种:1.JSONP 2.IFrame方式 3.通过flash实现 4.CORS跨域资源共享 ,这里我们主要关注的是在MVC里面的CORS ...
- 应如何取B/S的B端的IP
我们常讨论说要取真实IP,不同场景所谓的真实IP含义不一样. 如你要根据客户端IP去判断客户所在区域,那么要记录客户的出口IP,这里的出口IP才是你所谓的真实IP. 如你要判断多个客户端是不是同一个, ...
- Leetcode 45. Jump Game II
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- asp.net mvc bootstrap datatable 服务端分页
datatable 服务端分页 因项目需求变动,需处理大量数据,更改成服务端分页,自己两天的学习笔记 先上图[ jqueryui风格] 前端代码: @{ Layout = null;} <!DO ...
- 简析TCP的三次握手与四次分手
TCP是什么? 具体的关于TCP是什么,我不打算详细的说了:当你看到这篇文章时,我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我们就继续.它只是一个超级麻烦的协议,而它又是互联网的基础,也 ...
- 让 FreeBSD 和 Gentoo Linux 在 ZFS 存储卷上共存
自我回归到 Librem 15 已经有段时间了.我一般会选择 FreeBSD 来处理所有的事情,但有时会要访问一个运行在 Librem 平台上的 Linux OS,以便用它来帮助我对一些遗留的设备驱动 ...
- dom 节点篇 ---单体模式
<script> var creatTag={ oUl:document.createElement('ul'), oDiv:document.createElement('div'), ...
- JS中class和id的区别
class和id的区别 class用于css的,id用于js的. 1)class页面上可以重复.id页面上唯一,不能重复. 2)一个标签可以有多个class,用空格隔开.但是id只能有id.
- Python 类(一)
这一篇让先抽象的了解下类与实例 一类的定义 从具体的程序设计观点来看: 类是一种数据结构.我们可以使用类来定义包含数据值和行为特性的对象(类对象). 类是封装逻辑和数据的另一种形式. 面向对象设计观点 ...