JavaScript 面向对象介绍
来源:互联网 发布:淘宝网看手机 编辑:程序博客网 时间:2024/05/20 13:04
转载自 http://blog.csdn.net/ligang2585116
1. 构造函数
构造函数就是用new创建对象时调用的函数。使用构造函数的好处在于所有用同一个构造函数创建的对象都具有同样的属性和方法。
function Person(){}var p1 = new Person();console.log(p1.constructor === Person); // trueconsole.log(p1 instanceof Person); // true
可以使用构造函数来检查一个对象的类型,但还是建议使用instanceof来检查对象类型。因为构造函数属性可以被覆盖,并不一定完全准确。
示例:构造函数返回对象
function Foo(){ this.name = "foo"; return {name: "hhh"};}var f = new Foo();f.name; // hhhf.constructor; // Object
示例:构造函数返回原始类型
function Too(){ this.name = "too"; return "hhh";}var t = new Too();t.name; // toot.constructor; // Too
构造函数中显示调用return:
- 如果返回的值是一个对象,它会替代新创建的对象实例返回;
- 如果返回的值是一个原始类型,它会被忽略,新创建的对象实例会被返回。
改变原型对象
[[Prototype]]
属性只是包含一个指向原型对象的指针,并不是一个副本;任何对原型对象的改变都立刻反映到所有引用它的对象实例上。
示例:扩展原型对象
function Person(){}var p = new Person();p.sayHi(); // p.sayHi is not a function(…)Person.prototype.sayHi = function(){ console.log("hi");};p.sayHi(); // "hi"
注意:在一个对象上使用Object.seal()
或Object.freeze()
时,完全是在操作对象的自有属性,可以通过在原型上添加属性来扩展这些对象实例。
示例:冻结对象
function Person(name){}var p = new Person();Object.freeze(p);p.name = "ligang";Person.prototype.sayHi = function(){ console.log("hi");};console.log(p.name); // undefinedp.sayHi(); // "hi"
继承
JavaScript内建的继承方法被称为原型对象链,又称为原型对象继承。当一个对象的[[Prototype]]
设置为另一个对象时,就在这两个对象之间创建了一条原型对象链。
1. Object.prototype
所有对象都继承自Object.prototype
。
上述5种方法经由继承出现在所有对象中。
(1)valueOf() valueOf()
默认返回对象实例本身,可以定义自己的valueOf()
方法,定义的时候没有改变操作符的行为,仅仅定义了操作符默认行为所使用的值。
(2)toString()
一旦valueOf()
返回的是一个引用而不是原始值的时候,就会回退调用toString()
。
示例:
var obj1 = { valueOf: function(){ return "valueOf"; }, toString: function(){ return "toString"; }}var obj2 = { valueOf: function(){ return {name: "哈哈"}; }, toString: function(){ return "toString"; }}obj1 + ""; // "valueOf"obj2 + ""; // "toString"
2. 修改Object.prototype
在Object.prototype
添加方法,默认是可枚举的,意味着可以出现在for-in循环中。Douglas Crockford(JavaScript之父)推荐在for-in循环中始终使用hasOwnProperty()
。
var empty = {};Object.prototype.myName = "LIGANG";for(var prop in empty){ console.log(prop); // 会输出:myName}for(var prop in empty){ if(empty.hasOwnProperty(prop)){ console.log(prop); // 无任何内容输出 }}
所以,在进行for-in操作时,最好的方式就是增加hasOwnProperty()
判断;与此时同,不要修改Object.prototype
。
3. 对象继承
对象继承是最简单的继承类型,需要做的就是指定哪个对象是新对象的[[Prototype]]
。
创建对象过程中,字面量形式会隐式指定Object.prototype
为其[[Prototype]]
,也可以用Object.create()
方式显示指定。
var obj1 = {};var obj2 = Object.create(Object.prototype, {});
Object.create()
方法,第一个参数是需要设置为新对象的[[Prototype]]
的对象,第二个参数是一个属性描述对象,格式同Object.defineProperties()
示例:原型对象链(继承)
var person = { name: "person", sayName: function(){ console.log(this.name); }};var p1 = Object.create(person, { name: { cofigurable: true, enumerable: true, value: "ligang", writable: true }});
末端通常是一个Object.prototype
其[[prototype]]
被置为null。
示例:空对象
var obj1 = {};var obj2 = Object.create(null);"toString" in obj1; // true"toString" in obj2; // false
obj2没有原型对象链的对象。完全是一个没有任何预定义属性的白板,使其成为一个完美的哈希容器。
4. 构造函数继承
构造函数的所有对象实例共享同一个原型对象,所以它们都继承自该对象,但不能用原型对象继承自有属性。
function Person(name){ this.name = name; // 私有属性}Person.prototype.sayName = function(){ // 共用方法 console.log(this.name);};var p1 = new Person("ligang");var p2 = new Person("camile");
p1,p2都是构造函数Person的实例,其共享Person.prototype
原型对象。但其自有属性name不能通过原型对象继承。
总结:自有属性/方法通过构造函数定义,共有属性/方法通过原型对象继承!!!
六、对象模式
虽然JavaScript没有一个正式的私有(局部)属性的概念(ES6中出现了let语法,可以定义局部变量),但是可以创建仅在对象内可以访问的数据或函数。使用模块模式可对外界隐藏数据;也可以使用立即调用函数表达(IIFE)定义仅可被新创建的对象访问的本地变量和函数。
1. 私有成员和特权成员
var obj = (function(){ // 私有变量 var author = "ligang"; return { // 公共的方法和属性 getAuthor: function(){ return author; } };}());obj.author; // undefinedobj.getAuhtor(); // "ligang"
上述函数仅存在于被调用的瞬间,一旦执行后立即就被销毁了。
// 上述示例的等价写法var obj = (function(){ // 私有变量 var author = "ligang"; var getAuthor = function(){ return author; }; return { // 公共的方法和属性 getAuthor: getAuthor };}());
2. 混入
混入将一个属性从一个对象复制到另一个,从而使得接受者在不需要继承提供者的情况下获得其功能。和继承不同,混入令你在创建对象后无法检查属性来源。若你想要获得更强大的功能且需要知道该功能来自哪里,继承是首选!
function mixin(des, src){ for(var prop in src){ if(src.hasOwnProperty(prop)){ des[prop] = src[prop]; } } return des;}
注意上述方式,不是深拷贝!
3. 作用域安全的构造函数
function Person(name){ this.name = name;}var p1 = new Person("ligang");var p2 = Person("camile");console.log(p1 instanceof Person); // trueconsole.log(p2 instanceof Person); // false
作用域安全的构造函数是用不用new都可以被调用来生成新的对象实例的构造函数。其this在构造函数一开始执行就已经指向自定义类型的实例。当然,你可以根据new的使用与否决定构造函数的行为。
function Person(name){ if(this instanceof Person){ this.name = name; }else { return new Person(name); }}var p = Person("ligang");console.log(p instanceof Person); // true
许多内建构造函数,例如Array、RegExp不需要new也可以工作,正是因为它们被设计之初采用了作用域安全的构造函数。
- JavaScript 面向对象介绍
- JavaScript面向对象编程代码介绍
- JavaScript面向对象编程代码介绍
- JavaScript面向对象编程代码介绍
- JavaScript面向对象编程代码介绍
- javaScript 面向对象-对象
- 用面向对象的Javascript来介绍一下自己
- Javascript面向对象及组件的详细介绍(三)面向对象的拖拽
- 面向对象技术介绍
- 面向对象介绍
- 面向对象--介绍
- 面向对象介绍
- javascript 面向对象初探
- JavaScript 面向对象编程
- JavaScript 面向对象编程
- 面向对象的javascript
- javascript面向对象编程
- javascript的面向对象
- int,float,double型转换深析
- SQL语句输出直角三角形
- SAP修改物料价格那些事
- Spring3系列: Spring AOP——Pointcut,Advisor
- 实现一个选择排序程序,排序整型数组
- JavaScript 面向对象介绍
- select重置
- vs2013编译win-32位下的libevent-2.0.21-stable,debug版本
- IOS的Cookie之网页身份认证与Session的追踪
- 微信小程序实例:move事件导致navigator组件和tap事件无效
- poj Children of the Candy Corn(BFS+DFS)
- apache 配置 httpd-vhost.conf 。VirtualHost 配置更改域名,端口 。 无法访问 localhost
- MyBatis动态传入表名,字段名参数的解决办法
- JAVA 枚举类型 根据代码得到中文