≡
  • 网络编程
  • 数据库
  • CMS技巧
  • 软件编程
  • PHP笔记
  • JavaScript
  • MySQL
位置:首页 > 网络编程 > JavaScript

Javascript中的面向对象入门实例(二)

人气:696 时间:2018-09-25

这篇文章主要为大家详细介绍了Javascript中的面向对象入门实例(二),具有一定的参考价值,可以用来参考一下。

严格来说,Javascript并不是一门面向对象的语言,因为它没有原生提供完整的面向对象机制。但它的语言特性又允许我们去模拟大部分这些机制。

new操作符

Javascript中也用new操作符创建类的实例,例如:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
var arr = new Array(10); // 创建长度为10的数组
var date = new Date; // 不需要传参数给构造函数时,括号可以省略
与C#不同的是,Javascript中new的是函数而不是class,这个函数即为类的构造函数。在构造函数中,可以声明属性和方法。例如:

function Square() {
    this.length = 1;
    this.perimeter = function() {
        return this.length * 4;
    };
}

var square = new Square();
square.perimeter(); // 4
square.length = 10;
square.perimeter(); // 40
虽然上面的代码看上去很正常,但实际上存在一个缺陷:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
var square1 = new Square();
var square2 = new Square();
square1.perimeter === square2.perimeter; // false
由于每次创建Square对象执行构造函数时都创建了新的函数perimeter,所以多个Square对象的perimeter并非指向同一个函数。这样会造成内存的浪费。要解决这个问题,可以使用原型链。

原型链

Javascript中的对象都有一个内部属性__proto__(在新浏览器中已经变成可读可写的外部属性了)指向其构造函数的prototype;构造函数的prototype也是一个对象,所以它也有一个__proto__属性指向它的构造函数的prototype……如此逐层查找,直到__proto__属性的值是null为止。这就是原型链。下面以代码证实这一规则:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
var arr = new Array();
arr.__proto__ === Array.prototype; // true
那么Array.prototype.__proto__又是什么呢?在控制台打印出来可以发现,是一个Object对象,所以:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
Array.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__; // null
Object类是所有类型的基类,所以它的prototype的__proto__属性为null。最后得出arr的原型链为:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
arr.__proto__
Array.prototype
Array.prototype.__proto__
an Object object
object.__proto__
Object.prototype
Object.prototype.__proto__
null
原型链的用处在于:当访问对象的某个属性或方法时,如果对象本身没有这个属性或方法,就会在原型链中由浅到深进行查找(浅处优先)。同样地有代码可以证实这一规则:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
var arr = new Array();
// arr本身没有push
arr.hasOwnProperty('push'); // false
// 访问arr.push时实际上访问的是Array.prototype.push。
arr.push === arr.__proto__.push; // true
arr.push === Array.prototype.push; // true
不难发现,即使有多个Array对象,它们也是共享Array.prototype上的方法。所以,借助原型链就可以解决前面提到的多个函数副本浪费内存的问题:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
function Square() {
    this.length = 1;
}
Square.prototype.perimeter = function() {
    return this.length * 4;
};

var square1 = new Square();
var square2 = new Square();
square1.perimeter === square2.perimeter; // true

继承

原型链的层次结构跟面向对象的继承非常相似,所以原型链也可以用于模拟继承。先来看一个简单的例子:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
function Shape() {
    this.name = '形状';
}
Shape.prototype.perimeter = function() { };

function Square() {
    this.length = 1;
}
// Javascript中没有抽象类的概念,所以Shape是可以实例化的
Square.prototype = new Shape(); // important
Square.prototype.perimeter = function() {
    return this.length * 4;
};

var square = new Square();
square.name; // '形状'
square.perimeter(); // 4
其中最为关键的就是把一个Shape对象加入到Square的原型链中去。根据原型链的规则:
访问square.name时,实际上访问的是Square.prototype.name,也就是那个Shape对象的name属性。

调用square.perimeter()时,虽然Square.prototype和Shape.prototype中都存在perimeter方法,但根据浅处优先原则,调用的是Square.prototype.perimeter。
很明显,这跟继承的效果是一样的。

封装

目前Javascript没有任何机制可以控制属性和方法的可访问性,也就是说private和protected都无法实现。但是利用闭包的特性可以实现类似private的效果:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
function Square() {
    var length = 1;
    this.setLength = function(len) {
        length = len;
    };
    this.getLength = function() {
        return length;
    };
    this.perimeter = function() {
        return length * 4;
    };
}

var square = new Square();
square.perimeter(); // 4
square.setLength(10);
square.perimeter(); // 40
由于length变量的作用域是在Square内,所以外部无法访问,也就达到了私有的效果。但这样一来,三个方法就不能写到Square.prototype上,因为一旦它们脱离了Square的作用域,就无法访问length了。

鉴于封装特性难以实现,实际工作中更多是通过编码规范来进行约束。例如可以规定:名字以双下划线开头的属性或方法是private的,名字以单下划线开头的属性或方法是protected的。代码示例:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
function Square() {
    this.__length = 1;
}
Square.prototype.setLength = function(len) {
    this.__length = len;
};
Square.prototype.getLength = function() {
    return this.__length;
};
Square.prototype.perimeter = function() {
    return this.__length * 4;
};

var square = new Square();
square.perimeter();
square.setLength(10);
square.perimeter();

小结

最后,我们再来了解一下new操作符的大概执行过程:

创建一个新的空对象;
设置新对象的__proto__属性为构造函数的prototype;
以新对象为this执行构造函数。

如果以代码表示,则为:

/**
 * 面向对象入门实例(二)
 *
 * @param 
 * @arrange (512.笔记) www.q1010.com
 **/
// 以new Foo()为例
var obj = { };
obj.__proto__ = Foo.prototype;
Foo.call(obj);
大家不妨以此过程回顾前面的代码段。

本篇到此结束,下一篇讲述在Javascript中模拟面向对象的其他细节问题。

本文来自:http://www.q1010.com/174/1651-0.html

注:关于Javascript中的面向对象入门实例(二)的内容就先介绍到这里,更多相关文章的可以留意四海网的其他信息。

关键词:面向对象

您可能感兴趣的文章

  • Javascript中的面向对象入门实例(一)
  • Javascript的面向对象入门实例(三)
  • PHP 面向对象实现数据库登陆类的简单示例
  • php 完全面向对象操作mssql数据库类的入门实例
  • php 一个完全面向对象的RSS/XML类的简单示例
  • PHP 面向对象的mysql数据库操作类功能实例
上一篇:Javascript的面向对象入门实例(三)
下一篇:Javascript中的面向对象入门实例(一)
热门文章
  • js随机生成两位数
  • js 文字超出部分隐藏、点击显示更多示例
  • 原生JS+css 点击查看全文的简单示例(类似今日头条效果)
  • javascript实现文字隐藏、展开收起的简单示例
  • JS 展开/收起按钮显示隐藏文字示例
  • JavaScript 正则判断文本是否含有超链接的简单示例
  • 原生JS实现鼠标悬停图片显示文字的简单示例
  • JS 点击按钮显示更多内容的简单示例
  • 原生js for循环遍历二维数组、嵌套元素的简单示例
  • javascript 浮点数转换成整数三种方法
  • 最新文章
    • js获取时间,处理时间等的实现方法
    • JavaScript 判断小数是否相等的简单示例
    • JavaScript 获取数组极值的简单示例
    • JavaScript防抖 & 节流的简单示例
    • JavaScript深拷贝的简单示例
    • JavaScript数组降维的简单示例
    • JavaScript手机端判断浏览器类型的简单示例
    • JavaScript获取 URL 中的参数的简单示例
    • JavaScript以“天”为单位获取响应的时间戳的简单示例
    • JavaScript时间格式化的简单示例

四海网收集整理一些常用的php代码,JS代码,数据库mysql等技术文章。