JavaScript面向对象精要(一)

传统面向对象的语言几大特征:封装、继承、多态,在JavaScript中并不适用。JavaScript的弱类型特征允许你用比其他语言更少的代码完成同样的任务。无需提前设计好类再进行编码。需要一个具有某个字段的对象了?随时随地都可创建。Nicholas

C.Zakas著作《JavaScript面向对象精要》告知我们如何创建对象、定义自己的类型,使用继承以及其他各种操作来充分使用对象。总之,更全面理解和使用JavaScript所有的一切。

一、原始类型和引用类型

1. 什么是类型

JavaScript虽然没有类的概念,但依然存在两种类型:原始类型引用类型

原始类型保存为简单数据值;引用类型则保存为对象,其本质是指向内存位置的引用。

var obj = new Object();

变量实际上并不包含对象的实例,而是一个指向内存中实际对象所在位置的指针(或者说引用)。这是对象和原始值之间的一个基本区别。原始值都是直接保存在变量中。

:关于变量详见【变量、作用域和内存问题

2. 内建类型实例化

示例:对象字面形式

var obj1 = {};
var obj2 = new Object();

对象字面量,JavaScript引擎背后做的工作挺new Object()一样,除了没有调用构造函数。

示例:正则表达式字面形式

var reg1 = /^\d+$/g;
var reg2 = new RegExp("^\\d+$", "g");
reg2.toString(); // "/^\d+$/g"
reg2.source;     // "^\d+$"

使用字面下个形式创建正则,无需担心字符串中的转义字符。如果使用RegExp构造函数,传入模式的参数是一个字符串,需要转移。

3. 访问属性

示例:对待特殊字符的属性

var obj = {
    "ab": "yes",
    "a$b": "yes",
    "abc": "yes"
};
obj.ab;     // "yes"
obj["a$b"];    // "yes"
var name = "abc";
obj[name];  // "yes"

“中括号”可以处理动态决定访问哪个属性以及访问包含特殊字符的属性;其他方面同“点号”大致相同。

4. 鉴别引用类型

鉴别引用类型使用instanceof操作符。

示例:数组

Array.isArray()
[] instanceof Array

需要注意不同框架之间的判断。详见,【JavaScript高级技巧-安全的类型检测

5. 原始封装类型

示例:自动创建的基本包装类型

var name = "string";
name instanceof String; // false
new String("string") instanceof String; // true

临时对象,仅在值被读取时创建,然后立即被销毁。instanceof操作符并没有真的读取任何东西。

二、函数

函数也是对象。使函数不同于其他对象的特性是其内部具有[[Call]]属性。该属性无法通过代码访问而是定义了代码执行时的行为。ECMAScript定义typeof操作符对任何具有[[Call]]属性的对象返回“function”。

示例:判断是否为function

typeof function(){};    // "function"
typeof /\./;    // "object"

注意:某些浏览器曾经在正则表达式中包含[[Call]]属性,导致其被错误鉴别为函数。

1. 函数提升

声明本身会被提升,而包括函数表达式的赋值在内的赋值操作并不会提升;后面的函数声明可以覆盖前面的。

示例:函数提升

a();    // "a..."
b();    // Uncaught TypeError: b is not a function(…)
function a(){
    console.log("a");
};
function a(){
    console.log("a...");
};
var b = function(){
    console.log("b");
}

2. 改变this

示例:obj拥有sayName()方法

var obj = {
    name: "obj",
    sayName: function(age){
        console.log("my name is:" + this.name + ",age: " + age);
    }
}

(1)call()方法

var obj1 = {name: "call"};
obj.sayName.call(obj1, 25); // my name is:call,age: 25

(2)apply()方法

var obj2 = {name: "apply"};
obj.sayName.apply(obj2, [25]);  // my name is:apply,age: 25

(3)bind()方法

var obj3 = {name: "bind"};
var sayName = obj.sayName.bind(obj3);
sayName(25);    // my name is:bind,age: 25

注意call()apply()立即执行,bind()返回一个函数,并不是立即执行。

关于函数。详见,【JavaScript提升(你不知道的JavaScript)】、【函数表达式

三、理解对象

1. 定义属性

当一个属性第一次被添加给对象时,JavaScript在对象上调用一个名为[[Put]]的内部方法;当一个已有的属性被赋予一个新值时,调用的是一个名为[[Set]]的方法。

var person = {};
person.name = "lg";     // 调用[[Put]]
person.name = "ligang"; // 调用[[Set]]

2. 属性探测

if(person.age){
    // do something with age
}

当值是一个null、undefined、0、false、NaN或空字符串时评估为假。由于一个对象属性可以包含这些假值,所以上述示例可能导致错误的假定。注意,这个问题在短路&&同样存在。

if(age in person){
    // do something with age
}

in操作符是探测对象中属性是否存在的最好途径,且不会评估属性的值。

3. 属性类型

属性有两种类型:数据属性访问器属性

如果只需要保存数据,通常没有什么理由使用访问器属性–直接使用属性本身即可。但当你希望赋值操作会触发一些行为或者读取的值需要通过计算所需的返回值得到时,访问器属性会非常有用。

var person = {
    _name: "lg"
};
Object.defineProperty(person, "name", {
    get: function(){
        console.log("my name is:" + this._name);
        return this._name;
    },
    set: function(name){
        this._name = "爱新觉罗" + name;
    }
});
// 等价
var person = {
    _name: "lg",
    get name(){
        console.log("my name is:" + this._name);
        return this._name;
    },
    set name(name){
        this._name = "爱新觉罗" + name;
    }
};
person.name;    // my name is:lg
person.name = "ligang";
person.name;    // my name is:爱新觉罗ligang

Vue正式通过Object.defineProperty()对属性进行监听、通知处理。

注意:创建一个同时具有数据特征和访问器特征的属性,会得到一个错误。

时间: 2024-10-25 22:51:33

JavaScript面向对象精要(一)的相关文章

《Javascript面向对象精要》笔记

刚读过<Javascript面向对象精要>这本书,在现有的知识体系里面有一些新鲜的认识,记录一下. 原始类型和引用类型 Javascript存在两种类型:原始类型和引用类型.原始类型包括String.Number.Boolean.Null.Undefined,引用类型保存对象,其本质是对象所在内存位置的引用. 原始类型的赋值或者给函数传参,实际上都是传递原始类型值的拷贝: 引用类型则是引用的拷贝.修改其中一个引用的话,其他引用也会受到影响.如果对象中的某个属性也是对象,在对象拷贝时就会引入深拷

《javascript面向对象精要》读书笔记

<javascript面向对象精要> 买这本书的原因主要是因为作者,Nicholas C. Zakas 牛X闪闪的js专家,读过js高程的应该都知道他,而这本书是他的最新力作,感觉也是js高程的精华版,满满地全是姿势,但这本书可不适合入门,读之前最好略懂js. 第一章 原始类型和引用类型 原始类型还是老生常谈的那5个:boolean,number,string,null,undefined. 但我始终不认为typeof null 为object不应严重到作为一个错误来看待,毕竟null就是一个

03.JavaScript 面向对象精要--理解对象

JavaScript 面向对象精要--理解对象 尽管JavaScript里有大量内建引用类型,很可能你还是会频繁的创建自己的对象.JavaScript中的对象是动态的. 一.定义属性 当一个属性第1次被添加给对象时JavaScript在对上上调用了一个名为 [[Put]]的内部方法,该方法会在对象上创建一个新节点保存属性,就像 哈希表上第一次添加一个键一样这个操作不仅指定了初始值 也定义了属性的一些特征 1.1 [[Put]]内部方法 [[Put]]在对象上创建一个自有属性 1.2 [[Set]

JavaScript面向对象精要(二)

四.构造函数和原型对象 1. 构造函数 构造函数就是用new创建对象时调用的函数.使用构造函数的好处在于所有用同一个构造函数创建的对象都具有同样的属性和方法. function Person(){} var p1 = new Person(); console.log(p1.constructor === Person); // true console.log(p1 instanceof Person); // true 可以使用构造函数来检查一个对象的类型,但还是建议使用instanceof

02.JavaScript 面向对象精要--函数

在JavaScript中,函数其实也是对象.是函数不同于其他对象的特点是:函数存在一个被称为[[Call]]的内部属性.[[Call]]属性是函数独有的,表明该对象可以被执行.ECMAScript 定义了typeof操作符对具有[[Call]]属性的对象返回 "function".理解函数的行为是理解JavaScript的核心. 一.函数声明式和表达式 1.1 函数声明  以function开头后面跟着函数的名字 function add(num1,num2){ return num1

JavaScript面向对象精要(一)

数据类型 在JavaScript中,数据类型分为两类: 原始类型 保存一些简单数据,如true,5等.JavaScript共有5中原始类型: boolean:布尔,值为true或false number:数字,值为任何整型会浮点数值 string:字符串,值为由单引号或双引号括出的单个字符或连续字符(JavaScript不区分字符类型) null:空类型,其仅有一个值:nulll undefined:未定义,其仅有一个值:undefined var name = "Pomy"; var

01.JavaScript 面向对象精要--原始类型和引用类型

一.什么是类型 JavaScript 虽然没有类的概念.但依然存在两种类型:原始类型和应用类型. 原始类型保存为简单的数据值,引用类型则保存为对象,其本质是指向内存位置 的引用.也就是说:原始值被直接保存在对象内,而引用值则作为一个指针保存在 对象内,该指针指向实际对象在内存中的储存位置. 二.原始类型 2.1 JavaScript中5中原始类型:boolean,number,string,null,undefined  原始类型变量直接保存原始值(而不是一个指针),当你将原始值赋值给一个变量 

JavaScript面向对象精要(二)

构造函数和原型对象 构造函数也是函数,用new创建对象时调用的函数,与普通函数的一个区别是,其首字母应该大写.但如果将构造函数当作普通函数调用(缺少new关键字),则应该注意this指向的问题. var name = "Pomy"; function Per(){ console.log("Hello "+this.name); } var per1 = new Per(); //"Hello undefined" var per2 = Per(

javascript面向对象系列第一篇——构造函数和原型对象

× 目录 [1]构造函数 [2]原型对象 [3]总结 前面的话 一般地,javascript使用构造函数和原型对象来进行面向对象编程,它们的表现与其他面向对象编程语言中的类相似又不同.本文将详细介绍如何用构造函数和原型对象来创建对象 构造函数 构造函数是用new创建对象时调用的函数,与普通唯一的区别是构造函数名应该首字母大写 function Person(){ this.age = 30; } var person1 = new Person(); console.log(person1.ag