JS权威指南

JS权威指南

  • 书中错误
    • p161,isArray 函数中的 Function.isArray => Array.isArray

--- 对象 ---

对象属性

  1. constructor

constructor 指代创建这个对象的构造函数;

对象方法

  1. obj.hasOwnProperty('x')

检测指定的名字是否为对象的自有属性

  1. Object.keys(o)

keys() 返回对象 o 所有自有属性的名称组成的数组

  1. Object.getOwnPropertyNames(o)

返回对象 o 所有自有属性的名称(包括不可枚举属性)组成的数组

  1. Object.getOwnPropertyDescriptor({x: 1}, 'x')

返回对象特定属性的属性描述符

  1. Object.defineProperty(o, 'x', {get: function () { return 2 } } )

设置属性的特性

  1. Object.create()

创建一个拥有指定原型和若干个指定属性的对象

  1. Object.prototype.isPrototypeOf(o)

检测一个对象是否是另一个对象的原型

  1. Object.isExtensible(o)

判断对象是否可以扩展

  1. Object.preventExtensions(o)

可将对象设置为不可扩展

  1. Object.seal(o)

将当前已有的 configurable 设置为 false(不可删除,但可写,也可转换为只读)

  1. Object.freeze(o)

将当前对象冻结(configurable、writable 都会被设置为 false

  1. getPrototypeOf(o)

返回指定对象的原型

三类javascript对象

  • 内置对象(数组,函数,日期和正则)是由 ECMAscript 定义的对象或类;
  • 宿主对象是由js解释器所嵌入的宿主环境定义的;
  • 自定义对象是由运行中的 js 代码创建的对象;

判断对象的类型

var toString = Object.prototype.toString;
function getType(obj){
    return toString.call(obj).slice(8, -1);
}
// ---eg---: 
var o = {};
getType(o);     //"Object"

//简便方式
[].toString.call(5).slice(8, -1)      // 'Number'

对象特性

  1. 对象的原型指向另外一个对象,本对象的属性继承自它的原型对象;
  2. 对象的类 class 是一个标识对象类型的字符串;
  3. 对象的扩展标记指明了是否可以向该对象添加新属性;

对象的三个属性

  • 原型 prototype:原型属性是用来继承属性的
  • class
  • 可扩展性 extensible attribute
var p = {x: 1};
var o = Object.create(p);
Object.prototype.isPrototypeOf(o);

两类属性

  • 自有属性是直接在对象中定义的属性;
  • 继承属性是在对象的原型对象中定义的属性;

对象属性特性

  1. 可写 writable attribute,表明是否可以设置该属性的值;
  2. 可枚举 enumerable attribute,表明是否可以通过 for/in 循环返回该属性。当值为 false 时,Object.keys(obj),该属性不会被列出。
  3. 可配置 configurable attribute,表明是否可以删除或修改该属性;

通过原型继承创建对象

function inherit (p) {
    if(p == null) throw TypeError();
    if(Object.create) return Object.create(p);
    var t = typeof p;
    if(t !== 'object' && t !== 'function') throw TypeError();
    function f(){};
    f.prototype = p;
    return new f();
}

属性检测

  1. 通过 in 操作符,此方法适合明确要查找的属性时使用(会查找原型链);
var o = { x: 1 };
'x' in o;           // => true,存在自有属性x
'y' in o;           // => false,自有属性和继承属性都没找到'y'
'toString' in o;    // => true,存在继承属性'toString'
  1. hasOwnProperty() 方法可以检测是否为该对象的自有属性(不会查找原型链);
var o = { x: 1 };
o.hasOwnProperty('x');          // => true,存在自有属性
o.hasOwnProperty('y');          // => false, 不存在自有属性'y'
o.hasOwnProperty('toString');   // => false,不存在自有属性'toString'
  1. propertyIsEnumerable() 方法为 hasOwnProperty() 的增强版,在检测是否为自有属性的同时还要检测该属性的可枚举性;
var o = inherit( { y: 2 } );
o.x = 1;
o.propertyIsEnumerable( 'x' );                          // => true,'x'是可枚举的自有属性
o.propertyIsEnumerable( 'y' );                          // => false,'y'不是自有属性
Object.prototype.propertyIsEnumerable( 'toString' );    // => false,'toString'不可枚举

属性的特性

  • 数据属性特性:
    • value(值)
    • writable(可写性)
    • enumerable(可枚举性)
    • configurable(可配置性)
  • 存取器属性特性
    • get(读取)
    • set(写入)
    • enumerable
    • configurable

对象序列化

  • 序列化后传至后端(属性为 undefined 时,序列化会忽视该属性)
var obj = {
    x: undefined,
    y: true,
    z: [1, 2, 3],
    nullVal: null
};
JSON.stringify(obj);    //"{"y":true,"z":[1,2,3],"nullVal":null}"
  • JSON 数据转换为js对象
var obj = JSON.parse('{"x": 1}');
  • 自定义序列化(方法名必须为 toJSON
var obj = {
  x: 1,
  y: 2,
  o: {
    o1: 1,
    o2: 2,
    toJSON: function(){
      return this.o1 + this.o2;
    }
  }
}
JSON.stringify(obj);    //"{"x":1,"y":2,"o":3}"

--- 数组 ---

属性

length返回数字的长度

方法

第13条以后的为ES5新增方法,它们都不修改原数组

  1. join()

以传入的参数为分隔符拼接数组元素,返回生成的字符串(不修改原数组)

  1. reverse()

颠倒数组元素顺序,返回倒序后的数组(修改原数组)

  1. sort()

排序数组元素,如数组包含undefined值,则将其排至数组末尾,返回排序后的数组(修改原数组)

  • 比较函数:
    arr.sort( function( a, b ) { return a - b; }        //从小到大排序
    arr.sort( function( a, b ) { return b - a; }        //从大到小排序
    
  1. concat()

合并传入的数组元素,返回合并的新数组(不修改原数组)

  1. slice()

截取数组元素,返回由截取元素组成的新数组(不修改原数组)

  1. splice()

插入或删除数组元素,返回由删除的元素组成的新数组(修改原数组)

  • 删除操作(参数①为要删除的起始下标,参数②为要删除的项数)
     var a = [1, 2, 3];
     a.splice(0, 1);            // => [1], a为[2, 3]  
    
  • 插入操作(参数①指定插入位置,参数②为0,参数③为插入项)
     var a = [1, 2, 3];
     a.splice(1, 0, 4, 5);     // => [], a为[1, 4, 5, 2, 3]
    
  • 替换操作(参数①起始下标,参数②为删除的项数,参数③为插入项)
     var a = [1, 2, 3];
     a.splice(1, 1, 4);     // => [2], a为[1, 4, 2, 3]
    
  1. push()

在数组的尾部添加一个或多个元素,返回插入元素后数组的 length 值(修改原数组)

  1. pop()

删除数组最后一个元素,返回删除的元素(修改原数组)

  1. unshift()

在数组的头部添加一个或多个元素,返回插入元素后数组的 length 值(修改原数组)

  1. shift()

删除数组头部的一个元素,返回删除的元素(修改原数组)

  1. toString()

将数组每个元素转化为字符串,用逗号拼接,并输出(类似调用元素的 toString() 方法)

  1. toLocalString()

类似 toString() 方法,只是拼接方式使用本地化分隔符代替

  1. forEach()

从头至尾遍历数组,为每个元素调用指定的函数

  1. map()

返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组

  1. filter()

使用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组

  1. every()

测试数组的所有元素是否都通过了指定函数的测试,都通过才返回 true

  1. some()

测试数组中的某些元素是否通过了指定函数的测试,有一项返回 true 则返回 true

  1. reduce()

接收一个函数作为累加器,数组中的每个值(从左到右)开始合并,最终为一个值

  1. reduceRight()

接受一个函数作为累加器,让每个值(从右到左,亦即从尾到头)缩减为一个值。(与 reduce() 的执行方向相反)

  1. indexOf()

返回给定元素能找在数组中找到的第一个索引值,否则返回 -1(从头至尾开始查找)

  1. lastIndexOf()

返回指定元素在数组中的最后一个的索引,如果不存在则返回 -1(从尾至头开始查找)

数组检测

  1. ES5方法
    Array.isArray([])       // true
    
  2. 兼容处理
    var isArray = Array.isArray || function(o) {
        return typeof o === 'object' && Object.prototype.toString.call(o).slice(8, -1) === 'Array';
    };
    

类数组对象

常见的类数组对象有DOM操作返回的NodeList集合,以及函数内部的arguments对象

将类数组转化为数组的方法:

//方法一:
var args = Array.prototype.slice.call(arguments);

//方法二:
var args = [].slice.call(arguments);

//方法三:
var args = Array.from(arguments);

计算亮点之间的距离

function Point(x, y){
    this.x = x;
    this.y = y;
}

Point.prototype.r = function () {
    return Math.sqrt(this.x * this.x + this.y * this.y);
};

var p = new Point(1, 1);

跳转至淘宝

function moveon () {
    var answer = confirm('准备好了嘛?');
    if (answer) location = 'http://taobao.com';
}
setTimeout( moveon, 1000 );

兼容bind方法

if(!Function.prototype.bind){
    Function.prototype.bind = function(o /*, args */){
        var self, boundArgs;
        self = this;
        boundArgs = arguments;
        return function(){
            var args, i;
            args = [];
            for(i = 1; i < boundArgs.length; i++) args.push(bounddArgs[i]);
            for(i = 0; i < arguments.length; i++) args.push(arguments[i]);
            
        }
    }
}

输出调试消息至页面

function debug (msg) {
    var log = document.querySelector('#debuglog');
    if (!log) {
        log = document.createElement('div');
        log.id = 'debuglog';
        log.innerHTML = '<h1>Debug log</h1>';
        document.appendChild(log);
    }
    var pre = document.createElement('pre');
    var txt = document.createTextNode(msg);
    pre.appendChild(txt);
    log.appendChild(pre);
}

对象转到数字

  1. 空数组转数字为什么为 0
  • 中间的转换过程(对象转数字):

    //首先调用对象的valueOf()方法
    var arr = [];
    
    //如果对象存在valueOf方法并返回一个原始值
    arr.valueOf();          // => 空数组对象自身
    
    //否则,如果对象具有toString()方法:
    arr.toString();         // => ""
    
    //如果toString()方法返回一个原始值,则将其转换为数字
    Number("");             // => 0
    
    //否则抛出一个类型错误
    
  1. 具有一个元素的数组(值为数字)转换为数字
  • 转换过程:

    //首先调用对象的valueOf()方法
    var arr = [9];
    
    //如果对象存在valueOf方法并返回一个原始值
    arr.valueOf();          // => 数组对象自身
    
    /否则,如果对象具有toString()方法:
    arr.toString();         // => "9"
    
    //如果toString()方法返回一个原始值,则将其转换为数字
    Number("9");             // => 9
    
    //否则抛出一个类型错误
    
  1. 具有一个元素的数组(值为字符串)转换为数字
  • 转换过程

    //首先调用对象的valueOf()方法
    var arr = ['one'];
    
    //如果对象存在valueOf方法并返回一个原始值
    arr.valueOf();          // => 数组对象自身
    
    /否则,如果对象具有toString()方法:
    arr.toString();         // => "one"
    
    //如果toString()方法返回一个原始值,则将其转换为数字
    Number("9");             // => NaN
    
    //否则抛出一个类型错误
    

对象转换到字符串

同对象转到数字过程,只是先进行 toString 操作,再进行 valueOf 操作;

delete运算符

  1. 用来删除对象属性或者数组元素(不能删除通过 var 声明的变量);
  2. 再次访问被删除对象属性或数组元素时,返回 undefined;
  3. delete 操作不改变数组的长度;
  4. 可以通过 in 操作符检测属性是否存在;
  5. 只会断开属性和对象之间的联系,而不回去操作属性中的属性(见示例5);
var obj = {
    one: 'one',
    two: 'two'
};
delete obj.one;
'one' in obj;                // => false
console.log(obj.one);       // => undefined

var arr = [1, 2, 3];
delete arr[0];
console.log(1 in arr);
console.log(arr[0], arr.length);        // => undefined 3

// 示例5
var a = { p: { x: 1 } };
var b = a.p;
delete a.p;
console.log(b.x);           // => 1 ,该p属性下的x属性依然可以访问到;

eval()

  1. eval() 只有一个参数;

    • 如果传入的参数不是字符串,则直接返回这个参数;
    • 如果传入的值为字符串,则字符串会被当初 js 代码进行编译;
      • 编译失败会抛出语法错误;
      • 成功则开始执行代码,并返回字符串中的最后一个表达式或语句的值;
      • 如果最后一个表达式或语句没有值,则最终返回 undefined;
  2. eval() 具有改变局部变量的能力;

此处直接调用了 eval(),因此它总是在调用它的上下文作用域内执行(即与普通代码执行类似);

  var x = 'global';
  function f () {
      var x = 'local';
      eval("x += ' changed';");
      return x;
  }
  console.log(f(), x);        // => 'local changed global'
  1. 间接调用 eval() 则不能改变局部变量和函数;

此处间接调用 veal(),并没有改变函数内的变量 y,操作的对象为全局变量 y;

  var global_eval = eval,         //把eval赋值给一个全局变量保存
      y = 'global';
  function g () {
      var y = 'local';
      global_eval("y += ' changed';");        //间接调用eval()
      return y;
  }
  console.log(g(), y);        // => 'local global changed'

返回对象的类

function classof(o) {
    if (o === null) return "Null";
    if (o === undefined) return "Undefined";
    return Object.prototype.toString.call(o).slice(8,-1);
}

返回函数的名字

Function.prototype.getName = function(){
    if('name' in this) return this.name;
    return  this.toString().match(/function\s*([^(]*)\(/)[1];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,042评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,996评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,674评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,340评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,404评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,749评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,902评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,662评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,110评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,577评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,258评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,848评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,726评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,952评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,271评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,452评论 2 348

推荐阅读更多精彩内容

  • 第三章 类型、值和变量 1、存取字符串、数字或布尔值的属性时创建的临时对象称做包装对象,它只是偶尔用来区分字符串值...
    坤少卡卡阅读 628评论 0 1
  • 第十三章 Web浏览器中的JavaScript 在HTML里嵌入JavaScript 在HTML文档里嵌入客户端J...
    坤少卡卡阅读 300评论 0 0
  • 引子 十年前,梨花树下,一个身穿白衣的男子在树下抚琴,一个身穿红衣的女子在飞舞的梨花下伴着琴声舞...
    啊哈小仙女阅读 505评论 0 0
  • 今天是七夕,网上各种有关情人节的消息铺天盖地,各种网站也抓住救命稻草一样的打折促销。这种时候我会躲避网络。 我...
    FOX在笑阅读 671评论 1 0
  • 上一章内容看这里(๑• . •๑) 人类的诞生 -1- 那时候,有一个人叫挪亚,是亚当儿子该隐的后代。他是一个完全...
    心晴夜明阅读 6,765评论 0 1