数组,对象

数组

什么叫数组

一系列数据的集合,每一项可以保存任何类型的数据,称为数组的元素,每个元素之间用逗号隔开

// 数组格式:
[1,2,3]

数组的创建方式

//1)字面量(直接量)(推荐)
var arr = [1,2,3];

//2)使用构造函数创建
var arr = new Array();//创建一个空数组
var arr = new Array(7);//创建一个长度为7的数组(数组项都为undefined)
var arr = new Array('王大锤',18 ,'普通青年','广州');//创建数组并同时写入数据

数组操作

数组访问与写入
// 索引(下标):从0开始
var arr = ['html5','css3','javascript'];

// 访问
arr[0]; // 'html5'
arr[2]; // 'javascript'

// 写入
arr[3] = 'web前端';
// length:表示数组的长度
arr.length; // 3

数组遍历

// for循环
// 格式:for(变量初始化;判断条件;变量更新){执行语句}
var arr = ['html5','css3','javascript'];
for (var i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}
// 'html5'
// 'css3'
// 'javascript'

多维数组

var arr = [1, 2, 'html5', [3, 4, 'css3'], [5, 6, 'javascript']]
arr[3][2];  // 'css3'

数组方法

  • push: 往数组尾部添加一个或多个元素,返回数组新的长度

  • pop:删除数组最后一个元素,返回删除的元素

  • unshift:往数组开头添加一个或多个元素,返回数组新的长度

  • shift:删除数组第一个元素,返回删除的元素

  • sort:将数组中的元素排序,并返回排序后的数组

    • 默认以字符串的排列方式(转换成ASCII码进行对比)

  • reverse:将数组中的元素颠倒顺序,返回逆序后的数组

  • slice(start[,end]):返回数组的片段或子数组,从start开始到end(不包括end所对应的元素)

    • 如果省略end参数,则截取到数组的最后一项

  • splice(start,deleteNum,…items):在数组中插入、删除、替换的通用方法

    • start:起始索引位置
    • deleteNum:要删除的数量
    • items:插入的元素(可以是多个)
  • join(separator) 返回字符串值,其中包含了连接到一起的数组的所有元素

    • separator为分隔符,默认为逗号
  • concat() 返回一个新数组,这个新数组是由调用这个方法的数组和参数组成

    • 参数可以是多个

值类型与引用类型的区别

-- 值类型 引用类型
存储方式 直接存储数据本身 储存的是数据的引用,数据存储在堆内存中
内存分配 分配在栈中的 分配在堆中
效率 效率高,不需要地址转换 效率较低,需要进行地址转换
内存回收 使用完后立即回收 使用完后不立即回收,而是交给GC处理回收
赋值操作 创建一个新对象 创建一个引用

数组复制与传输

  • 如何复制数组
  • 把数组作为函数的参数

数组排序

  • 冒泡排序法
  • 选择排序法

ES5数组新增

Array.isArray() 判断是否为数组

// 案例
Array.isArray([1, 2, 3]) // true
Array.isArray(1)         // false

indexOf/lastIndexOf(keyword [,startIndex]) 索引方法

  • keyword: 要查找的项,
  • startIndex:查找起点位置的索引,该参数可选
// 案例
[1, 2, 3].indexOf(1)   // 0
[1, 2, 3].indexOf(2)   // 1
[1, 2, 3].indexOf(4)   // -1
[1, 2, 3].indexOf(1,1) // -1
[1, 2, 3].lastIndexOf(1) // 0 
// lastIndexOf() 返回的结果相同,不同的是从右往左索引

forEach(fn), map(fn), filter(fn),every(fn), some(fn) 遍历数组

以上方法都对数组中的每一项运行给定函数fn,,函数中有三个形参分别为

  • item:数组中的每一项,
  • index:遍历过程中对应的索引值,
  • array:对数组的引用

reduce(fn,initVal)和reduceRight(fn,initVal) 归并方法

  • fn(prev, cur, index, array): fn是每一项调用的函数,函数接受4个参数分别是
    • prev:前一次返回值,
    • cur:当前值,
    • index:索引值,
    • array:当前数组,
    • 函数需要返回一个值,这个值会在下一次迭代中作为prev的值

  • initVal: 迭代初始值(可选),如果缺省,prev的值为数组第一项


对象Object

新建对象

// 直接量(推荐):
var obj = {name:'小明',age:18}

// 构造函数:
var obj = new Object();

读取属性值

可以通过中括号或者点语法读取

var obj = {name: '小明', age: 18}
console.log(obj.name)   // 小明
console.log(obj['age']) // 18

给对象添加属性

也可以通过中括号,和点语法添加

obj.sex = '男';
obj.marry = false;
obj['weight'] = 60

循环遍历

  • for 循环
  • for...in

数组中的对象

[{
    name:'iphone7 plugs',
    price:5899.00,
    color:'土豪金',
    imgurl:'img/ip7.jpg'
},{
    name:'Note7',
    price:3899.00,
    color:'黑色',
    imgurl:'img/note7.jpg'
},{
    name:'荣耀7',
    price:1999.00,
    color:'白色',
    imgurl:'img/honor7.jpg'
}];

调用对象方法

var hero = {
    breed: 'Turtle',
    occupation: 'Ninja',
    say: function() {
        return 'I am ' + hero.occupation;
    }
}

hero.say();   // 'I am Ninja'
hero['say']() // 'I am Ninja'
// 尽量别使用引号,除非别无它法

修改属性方法

// 创建一个对象
var hero = {};

// 给对象添加一些属性和方法
hero.breed = 'turtle';
hero.name  = 'coyle';
hero.sayName = function() {
    return hero.name
}

// 调用方法
hero.sayName() // 'coyle'

// 我们可以删除一个属性
delete hero.breed;
console.log(hero.breed) // undefined

// 修改对象的属性
hero.name = 'ducky'
console.log(hero.name) // 'ducky'

对象的this

var hero = {
    breed: 'Turtle',
    occupation: 'Ninja',
    say: function() {
        return 'I am ' + this.occupation;
    }
}

hero.say() // 'I am Ninja'

构造函数创建对象

function Hero () {
    this.occupation = 'Ninja'
} 

var h1 = new Hero()
h1.occupation = 'Ninja'
h1.constructor // function Hero () {...}  
// 使用构造函数的好处之一就是可以在创建对象的时候接收一些参数,按照惯例,我们应将构造函数首字母大写,以便显著区分其他函数

// 但是如果调用构造函数是忽略了new 操作符
var h2 = Hero()
typeof h2 // undefined
typeof h2.occupation // 'TypeError: Cannot read property occupation of undefined'

instanceof操作符

通过instanceof操作符,我们可以测试一个对象是不是由某个构造函数创建的

function Hero (name) {
    this.name = name
}
h1 = new Hero('coyle')

h1 instanceof Hero // true

对象比较

var obj1 = {breed: 'dog'};
var obj2 = {breed: 'dog'};
obj1 === obj2 // false

var mydog = obj1
// mydog 和 obj1 所指向的对象是相同的
mydog === obj1 // true
mydog === obj2 // false

内建对象

Object

Object 是 JavaScript 中所有对象的父级对象,

var o = {}
var o = new Object()
// 上面这两行代码的执行结果是等价的

o.constructor // 返回构造函数的引用 
// function Object() {native code}

o.toString()  // 返回对象的描述字符串
// [object object]

o.valueOf()   // 返回对象的单值描述信息,通常返回的就是对象本身
// {}
o.valueOf === o // true
Array

同上, Array 是 JavaScript 中所有数组的父级对象

var arr = [];
var arr = new Array();
// 上面也是等价的

arr.constructor // function Array () { [native code] }
arr.toString()  // ''
arr.valueOf()   // []
// 既然数组也是由构造器生成,那个这也意味着数组实际上也是一个对象
typeof arr // object

数组与对象的区别

  • 数组的属性名是从0开始递增,并自动生成数值
  • 数组拥有一个记录元素数量的属性
  • 数组在父级对象的基础上扩展了更多额外的内建方法
// 我们来验证一下数组于对象的区别
var a = [], o = {};
a.length // 0
o.length // undefined
Function

函数的构造器是Function(), 也就是说 Function 是所有的函数的父级对象

与其他内建对象一样,函数对象中也有constructor的属性,其引用的就是 Function() 这个构造函数

function fun1(a) {
    return a
}

fun1.constructor // function Function() { [native code] }
fun1.toString() 
// ' function fun1(a) { return a } '
// 但我们如果想用这个方法查看内建函数的源码的话 就会的到一个毫无用处的字符串[native code]
parseInt.toString() // function parseInt() { [native code] }

fun1.length // 1
// 另外函数也有length属性,用于记录实参的数量

prototype 属性是 JavaScript 中使用最广泛的函数属性

  • 每个函数的 prototype 属性都指向了一个对象
  • 它只有在该函数是构造函数时才发挥作用
  • 该函数创建的所有对象都会持有一个该 prototype 属性的引用,并可以将其做自身的属性来使用
// 我们来演示一下 prototype 属性的使用
var ninja = {
    name: 'Ninja',
    say: function() {
        return 'I am a ' + this.name
    }
}

function F() {}
typeof F.prototype // object

// 我们将F.prototype进行修改
F.prototype = ninja;
var baby_ninja = new F()
console.log(baby_ninja.name) // 'Ninja'
baby_ninja.say() // I am a Ninja

arguments对象

arguments看上去像一个数组,但他实际是一个类似数组的对象,他和数组类型是应为其中也包含了索引元素和length属性,但相似之处也就到此为止了,arguments不提供像sort(),push等方法

function f () {
    return arguments
}

f(1,2,3) // [1, 2, 3]

// 我们可以使用call()实现
function f() {
    var args = [].slice.call(arguments);
    return args.reverse()
}

数据类型判断

Object.prototype.toString.call('s')   // [object String]
Object.prototype.toString.call(1)     // [object Number]
Object.prototype.toString.call([1,2]) // [object Array]

var toStr = Object.prototype.toString

(function() {
    return toStr.call(arguments)
})() // [object Arguments]

toStr.call(document.body) // [object HTMLBodyElement]

apply和call

在 JavaScript 中每个函数都有 apply() 和 call() 两个方法,你可以用它们来触发函数,并指定相关的调用参数

此外,这两个方法还有另外一个功能,他可以让一个对象去借用另一个对象的方法,并为己所用。这也是一种非常简单的代码重用

var some_obj = {
    name: 'Ninja',
    say: function(who) {
        return 'Haya ' + who + 'I am a ' + this.name 
    }
}

some_obj.say('coyle') // Haya coyle I am a Ninja
var my_obj = {name: 'ducky'};
some_obj.say.call(my.obj, 'coyle') // Haya coyle I am a ducky
//

由于我们在调用say()函数的对象方法call()时传递了两个参数,对象my_obj,和字符串'coyle',这样一来,当say()被调用时,其中的this被设置成my_obj的引用。所以,我们看到,this.name返回的不再是Ninja,而是my_obj的name

另外,如果我们没有将对象传递给call()的首参数,或者传递的是null,它的调用对象会被默认为全局对象

apply 和 call 的工作方式基本相同,唯一的不同是参数传递形式,apply接受的是数组

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

推荐阅读更多精彩内容