1.对象的定义

ECMAScript中,对象是一个无序属性集,这里的“属性”可以是基本值、对象或者函数

2.数据属性与访问器属性

  • 数据属性即有值的属性,可以设置属性只读、不可删除、不可枚举等等

  • 访问器属性是用来设置getter和setter的,在属性名前加上”_”(下划线)表示该属性只能通过访问器访问(私有属性),但并不是说添个下划线就把属性变成私有的了,这只是习惯约定的一种命名方式而已。访问器属性没什么用,原因如下:

    var book={
    _year:2004,
    edition:1
    }
    Object.defineProperty(book,"year",{
    get:function(){
    return this._year;
    },
    set:function(newValue){
    if(newValue>2004){
    this._year=newValue;
    this.edition+=newValue-2004;
    }
    }
    });
    book.year=2005;
    alert(book.edition);
    /*
    for(var attr in book){
    showLine(attr + ' = ' + book[attr]);
    }
    */

    高程中使用了上面的示例代码,原理是book对象的属性中_year是数据属性,而year是访问器属性,利用gettter和setter可以插入读写控制,听起来不错。

    但问题是_year和edition都是可枚举的,也就是说用for...in循环可以看到,而访问器属性year却是不可枚举的。应该公开的访问器不公开,却把应该隐藏的私有属性公开了。

    除此之外,这种定义访问器的方式并不是全浏览器兼容的,[IE9+]才完整支持,当然,也有适用于旧浏览器的方式(__defineGetter__()和__defineSetter__()),还是相当麻烦。

    总之,访问器属性没什么用。

3.构造函数

function Fun(){} var fun = new Fun();其中Fun是构造函数,与普通函数没有任何声明方式上的区别,只是调用方式不同(用new操作符调用)而已

构造函数可以用来定义自定义类型,例如:

function MyClass(){
this.attr = value;//成员变量
this.fun = function(){...}//成员函数
}

与Java的类声明有些相似,但也有一些差异,比如this.fun只是一个函数指针,因此完全可以让它指向可访问的其它函数(如全局函数),但这样做会破坏自定义对象的封装性

4.函数与原型prototype

  1. 声明函数的同时也创建了一个原型对象,函数名持有该原型对象的引用(fun.prototype)

  2. 可以给原型对象添加属性,也可以给实例对象添加属性,区别是原型对象的属性是该类型所有实例所共享的,而实例对象的属性是非共享的

  3. 访问实例对象的属性时,先在该实例对象的作用域中查找,找不到才在原型对象的作用域中查找,因此实例的属性可以屏蔽原型对象的同名属性

  4. 原型对象的constructor属性是一个函数指针,指向函数声明

  5. 通过原型可以给原生引用类型(Object,Array,String等)添加自定义方法,例如给String添加Chrome不支持但FF支持的startsWith方法:

    var str = 'this is script';
    //alert(str.startsWith('this'));//Chrome中报错
    String.prototype.startsWith = function(strTarget){
    return this.indexOf(strTarget) === 0;
    }
    alert(str.startsWith('this'));//不报错了

    注意:不建议给原生对象添加原型属性,因为这样可能会意外重写原生方法,影响其它原生代码(调用了该方法的原生代码)

  6. 通过原型可以实现继承,思路是让子类的prototype属性指向父类的实例,以增加子类可访问的属性,所以用原型链连接之后

    子类可访问的属性
    = 子类实例属性 + 子类原型属性
    = 子类实例属性 + 父类实例属性 + 父类原型属性
    = 子类实例属性 + 父类实例属性 + 父父类实例属性 + 父父类原型属性
    = ...

    最终父父...父类原型属性被替换为Object.prototype指向的原型对象的属性

    具体实现是SubType.prototype = new SuperType();可称之为简单原型链方式的继承

5.创建自定义类型的最佳方式(构造函数模式 + 原型模式)

实例属性用构造函数声明,共享属性用原型声明,具体实现如下:

    function MyObject(){
//实例属性
this.attr = value;
this.arr = [value1, value2...];
}
MyObject.prototype = {
constructor: MyObject,//保证子类持有正确的构造器引用,否则子类实例的constructor将指向Object的构造器,因为我们把原型改成匿名对象了
//共享属性
fun: function(){...}
}

6.实现继承的最佳方式(寄生组合式继承)

function object(obj){//返回原型为obj的没有实例属性的对象
function Fun(){}
Fun.prototype = obj;
return new Fun();
}
function inheritPrototype(subType, superType){
var prototype = object(superType.prototype);//建立原型链,继承父类原型属性,用自定义函数object处理是为了避免作为子类原型的父类实例具有实例属性,简单地说,就是为了切掉除多余的实例属性,可以对比组合继承理解
prototype.constructor = subType;//保证构造器正确,原型链会改变子类持有的构造器引用,建立原型链后应该再改回来
subType.prototype = prototype;
} function SubType(arg1, arg2...){
SuperType.call(this, arg1, arg2...);//继承父类实例属性
this.attr = value;//子类实例属性
}
inheritPrototype(SubType, SuperType);

具体解释见代码注释,这种方式避免了SubType.prototype = new SuperType();简单原型链的缺点:

  • 子类实例共享父类实例引用属性的问题(因为原型引用属性是所有实例共享的,建立原型链后父类的实例属性就自然地成了子类的原型属性)。

  • 创建子类实例时无法给父类构造函数传参

7.实现继承的最常用方式(组合继承)

把上面的inheritPrototype(SubType, SuperType);语句换成:

SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;

这种方式的缺点是:由于调用了2次父类的构造方法,会存在一份多余的父类实例属性,具体原因如下:

第一次SuperType.call(this);语句从父类拷贝了一份父类实例属性给子类作为子类的实例属性,第二次SubType.prototype = new SuperType();创建父类实例作为子类原型,此时这个父类实例就又有了一份实例属性,但这份会被第一次拷贝来的实例属性屏蔽掉,所以多余。

js创建对象的最佳方式的更多相关文章

  1. js 创建对象的多种方式

    参考: javascript 高级程序设计第三版 工厂模式 12345678910 function (name) { var obj = new Object() obj.name = name o ...

  2. 基础2:js创建对象的多种方式

    js创建对象的多种方式 1. 工厂模式 function createPerson(name) { var o = new Object() 0.name = name return o } var ...

  3. js创建对象的多种方式及优缺点

    在js中,如果你想输入一个的信息,例如姓名,性别,年龄等,如果你用值类型来存储的话,那么你就必须要声明很多个变量才行,变量声明的多了的话,就会造成变量污染.所以最好的方式就是存储到对象中.下面能我就给 ...

  4. javascript(js)创建对象的模式与继承的几种方式

    1.js创建对象的几种方式 工厂模式 为什么会产生工厂模式,原因是使用同一个接口创建很多对象,会产生大量的重复代码,为了解决这个问题,产生了工厂模式. function createPerson(na ...

  5. JS创建对象的方式有几种

    相信但凡作为一个前端工程师,都被面试到过这个面试题目,HR考察的就是对oop思想的理解. 作为一个从后端转过来的怂逼,oop一直是心中的永远的痛啊. 这几天一直在通读js高级程序设计,重复理解js创建 ...

  6. JS创建对象的方式

    1.采用直接量创建方式:系统会使用new方式自动创建对象 var o = {x:1,y:2,z:2}; 2.采用new关键字创建对象:采用构造函数创建对象 var o = new Object();/ ...

  7. JS基础语法---创建对象---三种方式创建对象:调用系统的构造函数;自定义构造函数;字面量的方式

    创建对象三种方式: 调用系统的构造函数创建对象 自定义构造函数创建对象(结合第一种和需求通过工厂模式创建对象) 字面量的方式创建对象 第一种:调用系统的构造函数创建对象 //小苏举例子: //实例化对 ...

  8. JS创建对象篇

    JS创建对象篇 Object构造函数创建 var person = new Object(); person.name = "Tom"; person.age = 10; pers ...

  9. Node.js初探之GET方式传输

    Node.js初探之GET方式传输 例子:form用GET方法向后台传东西 html文件: <form action="http://localhost:8080/aaa" ...

随机推荐

  1. GPU Skin

    http://blog.csdn.net/leonwei/article/details/77387357 TPOSE存vbo 每根骨骼的matrices存在貼圖裏用vertex fetch 做GPU ...

  2. 算法导论-顺序统计-快速求第i小的元素

    目录 1.问题的引出-求第i个顺序统计量 2.方法一:以期望线性时间做选择 3.方法二(改进):最坏情况线性时间的选择 4.完整测试代码(c++) 5.参考资料 内容 1.问题的引出-求第i个顺序统计 ...

  3. Android百度地图(二)结合方向传感器我们自己定位哪里走

    Android百度地图(二)结合方向传感器我们自己定位哪里走 本文代码在http://blog.csdn.net/xyzz609/article/details/51943556的基础上进一步改动.有 ...

  4. Docker解析及轻量级PaaS平台演练(三)--Dockerfile编写

    在本篇中将介绍Dockerfile的编写 除了通过修改Image,创建Container,在打包成Image来创建我们需要的Image之外 我们还可以编写Dockerfile文件,通过build来创建 ...

  5. Spark(八) -- 使用Intellij Idea搭建Spark开发环境

    Intellij Idea下载地址: 官方下载 选择右下角的Community Edition版本下载安装即可 本文中使用的是windows系统 环境为: jdk1.6.0_45 scala2.10. ...

  6. 淘宝JAVA中间件Diamond详解(二)---原理介绍

    转:http://blog.csdn.net/anhuidelinger/article/details/70314744 大家好,通过第一篇的快速使用,大家已经对diamond有了一个基本的了解.本 ...

  7. vue单文件 style important引入样式

    使用@import引入外部css,作用域是全局的 <template> </template> <script> export default { name: &q ...

  8. Altium Designer 10 | 常用库及部分元件名中英文对照表

    ———————————————————————————————————————————— 常用库及部分元件名中英文对照表 - - - - - - - - - - - - - - - - - - - - ...

  9. STM32F103RB, KEIL编译出错:cannot open preprocessing output output file &quot;.\神舟i号\main.d&quot; no such file or

    STM32F103RB,   KEIL编译出错:cannot open preprocessing output output file ".\神舟i号\main.d" no su ...

  10. vs2017 生成代码策略 旧的 ObjectContext

    新版本的VS中已经去掉了生成ObjectContext的功能,需要手动下载一个生成ObjectContext的T4模板.在模型设计器的上下文菜单中选择添加代码生成项,在联机模板中选择对应EF版本的Ob ...