8.01 - 介绍一下对象
对象这辈子是不可能的了,啊呸。。简单来说,对象就是一个容器,与数组一样是用来存放数据的(实际上说过,数组是一个特殊的对象),但是与数组有很大的一些区别,主要表现在对象中存放的数据,辨识度更高,不分区分顺序,在JavaScript中也被称之为 JSON(JavaScript Object Notation)
基本资料
身高,年龄,三围...生成方法
字面量
var json = {}; console.log(typeof json);// object
Object 函数
var json = Object(); var json1 = new Object(); console.log(typeof json,typeof json1);// Object object
结构相关
键与值(key:value)
简单来说键是对象中用于
区别对象中不同的数据
的标记,也称之为对象的属性,一般为区分大小写的字母或者数字
组成而值则为具体所存储的数据,也称之为对象的属性值,可以为任意的JavaScript中的数据类型,包扩方法以及对象本身
// key 是键 字符串 "value" 是这个对象下 key键对应的值 { key:"value" }
多条数据时逗号隔开,最后一条数据不要写逗号
{ key:"value", name:"小花", arg:18, hobby:function(){ alert("买买买"); } }
关于键的引号
通常情况下,把对象作为临时存储的容器时,可以不用给键值带上引号,但是当作为传输的数据或者json格式的字符串的时候必选
严格的给键带上双引号
var data = '{"name":"小花","arg":18,"sex":"女"}'; // 或者是一些不规范的键 var json = { "a b":1, "a-b":2 }; console.log(json["a b"]);// 1 console.log(json["a-b"]);// 2
数据的读写方式
写入(存储数据)
定义的时候存储
var json = { key:"value", name:"小花", arg:18, hobby:function(){ alert("买买买"); } }; console.log(json);// {key: "value", name: "小花", arg: 18, hobby: ƒ}
赋值的方式
// 1. 普通对象 var json = {}; json.key = "value"; json["name"] = "小花";// 中括号读取 json.arg = 18; json.hobby = function(){ alert("买买买"); }; console.log(json);// {key: "value", name: "小花", arg: 18, hobby: ƒ} // 2. Object 方法生成的对象为一个空对象只能用赋值的方式添加属性与值 var obj = new Object(); console.log(obj); // {} obj.name = "小草"; console.log(obj); // {name: "小草"}
赋值会改变原有的数据
var json = {name:"小花"}; console.log(json);// 小花 json.name = "小草"; console.log(json);// 小草
读取(获取存储的数据)
对象.属性名
var json = { key:"value", name:"小花", arg:18, hobby:function(){ alert("买买买"); } }; console.log(json.name);// "小花" json.hobby();// "买买买"
对象["属性字符串"]
当属性名为变量时,必须为中括号的形式
// json[string] console.log(json["name"]);// "小花" json["hobby"]();// "买买买" // json[var] var vArg = "arg"; console.log(json.vArg);// undefined console.log(json[vArg]);// 18
for in
概述
for in 类似使用for遍历数组,同样是为了遍历对象中的所有成员时,才会使用到
注意点
它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性。
它不仅遍历对象自身的属性,还遍历继承的属性。
与普通for循环一样只有一条语句是可以省略花括号
代码案例
var json = { name:"小花", arg:18, hobby:function(){ alert("买买买"); } }; for(var key in json){ console.log(key);// 输出键的变量key:"name" "arg" "hobby" console.log(json[key]);// 输出键对应的值: "小花" 18 function }
删除
delete 操作符
概述:通过delete操作符删除的属性键完全从对象中去除
代码案例
var json = { name:"小花", arg:18, hobby:function(){ alert("买买买"); } }; console.log(json.arg);// 18 delete json.arg; console.log(json.arg);// undefined
对象的优点及其相关
对象是一个特殊的数据类型,可以被赋值给变量,也可以被作为参数传递
对象作为字面量书写时需要在开始与结束加上括号,避免与代码块的语法冲突
作为参数传递时可以实现设置默认参数,从而缺省减少参数,并且不分顺序
辨识度高,通过属性名可以很快的辨别存储的是什么数据值
代码案例
<div id="test"></div>
<script>
function rect( dom, json ){
var arg = {
width : 200,
height : 200,
bg : "blue"
};
// json 参数存在时
if(json)for(var k in json)arg[k] = json[k];
dom.style.cssText =
"width:"+arg.witch+"px;height:"+arg.height+"px;background-color:"+arg.bg+";";
}
// 设置div的宽度高度为 100 背景色使用默认值
rect(test,{
width : 100,
height : 100
});
</script>
8.02 - 对象的相关方法
对象本身的方法
对象本身的方法是指,Object函数下直接定义的方法,与实例无关
Object.keys(json)
概述:返回 json 对象所有
自身的属性名数组
代码案例
var json = { name:"小花", arg:18, hobby:function(){ alert("买买买"); } }; console.log( Object.keys(json) );// ["name","arg","hobby"]
对象的实例的方法
对象的实例的方法是指,具体的所有被实例化的对象下都拥有的方法,改方法定义在 Object 函数的构造函数下( Object.prototype )
json.hasOwnProperty(key)
概述:判断 key 是否是 json 实例对象下是否
自身拥有 key 属性
,返回一个布尔值代码案例
var json = { name:"小花", arg:18, hobby:function(){ alert("买买买"); } }; console.log( json.hasOwnProperty("sex") );// false console.log( json.hasOwnProperty("name") );// true
其他相关方法
一些与对象,json相关的方法,这些方法既不是对象函数本身的,也不是对象的实例的
JSON.stringify(value[, repelacer][, space])
概述:把一个json对象,或者数组对象,转换为对应格式的字符串的方法,通常使用在进行数据传输时
参数
value:需要进行转换的对象或者数组
repelacer:可选参数,改参数可以为一个
方法
或者一个数组
方法:
参数为传入每个成员的键和值,但是第一次的key为空字符串,value为对象本身
第二次起传入的对象使用的是上一次的返回值而不是原始值
如果此函数返回 undefined,则排除成员
数组:只会返回数组成员中字符串对应的属性
space:将对象字符串转为缩进的格式,并设置缩进的空格数
特性
自动排除值为方法的属性
代码案例
无参额外数
var json = { "name":"小花", "arg":18, "hobby":function(){ alert("买买买"); } }; var arr = JSON.stringify(json); console.log(arr);// {"name":"小花","arg":18} 自动排除了方法值
space 参数
var arr = JSON.stringify(json,null,4); console.log(arr); /* 输出如下格式 { "name": "小花", "arg": 18 } */
repelacer 参数
数组参数
var arr = JSON.stringify(json,["arg"],4); console.log(arr); /* 输出如下格式 { "arg": 18 } */
方法参数
var json = { "name":"小花", "arg":18, "sex":"man" }; var arr = JSON.stringify(json,function(key,value){ // 第一次必须返回value 从第二次开始操作每个属性的值 if(key === "")return value; // 当返回值是 undefined时,删除对应的属性 if(key === "arg"){ return undefined; } return "----" + value + "----"; }); console.log(arr);// {"name":"----小花----","sex":"----man----"}
JSON.parse(string[, repelacer])
概述:把JSON字符串转变成对象
参数:
string:需要进行解析的字符串
repelacer:可选
方法
参数,对数组的成员方法:
参数为传入每个成员的键和值,但是第一次的key为空字符串,value为对象本身
第二次起传入的对象使用的是上一次的返回值而不是原始值
如果此函数返回 undefined,则排除成员
参数规范:
参数字符串的结尾不能有逗号否则会报错
字符串中的键值必须添加双引号
// 末尾出现逗号 var jsonString = '{"name":"小花","arg":{"a":20,"c":30},"sex":"man",}'; JSON.parse(jsonString);// Unexpected token , in JSON at position 47
代码案例:
无额外参数时
var josnString = '{"name":"小花","arg":{"a":20,"c":30},"sex":"man"}'; var json = JSON.parse(josnString); console.log(json); // {name: "小花", arg: {…}, sex: "man"}
方法参数
var jsonString = '{"name":"小花","arg":18,"sex":"man"}'; var arr = JSON.parse(jsonString,function(key,value){ // 第一次必须返回value 从第二次开始操作每个属性的值 if(key === "")return value; // 当返回值是 undefined时,删除对应的属性 if(key === "arg"){ return undefined; } return value + "哟"; }); console.log(arr);// {name: "小花哟", sex: "man哟"}
eval(string)
概述:将string参数解析为JS代码
代码案例:
定义一个方法并做一个字符串加法
eval("function a(){ alert(1+1) }"); a();// 2
解析一个JSON字符串
var json = eval("({a:1,b:2})");// 必须在左右拼接上带上括号 console.log(json.a);// 1
JSON兼容
JSON 对象在 IE8- 并不支持,为了避免兼容问题可以采用 eval 方法处理,或者引用 JSON2 兼容文件:
源码地址:https://github.com/douglascrockford/JSON-js/blob/master/json2.js
8.03 - 对象与this之间的那些事
函数内部的 this 指向与函数所属的对象息息相关,通过 this 关键字我们可以简写代码,并且是面向对象编程的关键
但是js里的this指向其实很简单总结的一句话就是:this指向函数在执行时的触发对象
一些this指向情况
函数自执行时,指向window
function fn(){console.log(this);};
fn();// window
事件函数的this指向触发事件的元素
<button id="btn">点我啊!</button>
<script>
btn.onclick = function(){
console.log(this); // <button id="btn">点我啊!</button>
}
</script>
对象下的函数指向直属的对象
var json = {
fns : {
fn : function(){console.log(this);}
},
fn : function(){console.log(this);}
};
console.log(json.fn());// 指向 json {fns: {…}, fn: ƒ}
console.log(json.fns.fn());// 指向 fns {fn: ƒ}
对象下的函数被事件触发时指向触发事件的元素
<button id="btn">点我啊!</button>
<script>
var json = {
fns : {
fn : function(){console.log(this);}
}
};
btn.onclick = json.fns.fn;// <button id="btn">点我啊!</button>
</script>
改变this指向的方法
call(thisArg,arg1,arg2,arg3,...)
概述:
call()
方法可以代替直接括号执行的方式,调用一个函数,并改变改函数内部的this指向
为第一个参数,之后的参数对应改函数的原有参数代码案例:
简单的案例
var json = { name : "json", fn : function(arg){ console.log(arg + " " + this.name); } }; var json1 = { name : "json1" }; // 默认指向 console.log( json.fn("hello") );// "hello json" // 第一参数为 this 指向的参数,第二参数起为函数原有的实际参数 console.log( json.fn.call(json1,"hello") );// "hello json1"
运算方法
var tool = { add : function(){ return this.a + this.b; }, reduce : function(){ return this.a - this.b; }, calc : function(num,arg){ return this[arg].call(num); } }; var num = { a : 10, b : 5 }; tool.calc(num,"add"); // 15 tool.calc(num,"reduce"); // 5
apply(thisArg[, argArray])
概述:
apply()
方法可以代替直接括号执行的方式,调用一个函数,并改变改函数内部的this指向
为第一个参数,之后的参数为一个数组或者类数组,其每个成员代表该函数的对应参数代码案例:
简单的理解下apply的第二参数
function fn(a,b,c){ console.log(this.n + a + b + c ); } var num = {n:10}; fn.apply(num,[1,2,3]);// 16 // 与call方法对比 fn.call(num,1,2,3); // 16
通过 Math 求一组数字的最大值
var num = [10,20,1,60,12,38]; console.log( Math.max.apply(null,num) );// 60
bind(thisArg,arg1,arg2,arg3,...)
概述:与call类似,同样是改变函数的内部指向为 thisArg ,以及对应参数列表,但是区别在于,bind执行后是返回一个改变过后的函数,而不是直接执行函数
代码案例
简单使用
var num = {a:1,b:2}; function add(a,b){ return this.a + this.b; } var _add = add.bind(num); _add();// 3
点击事件直接传递参数
document.onclick = fn.bind(null,1,2,3);// 1 2 3 function fn(a,b,c){ console.log(this,a,b,c); }
8.04 - 对象拓展
对象的一些小知识
万物皆对象
JavaScript里面实际上所有的东西,都是对应的对象实例化出来的,数字 字符串 方法等等也是有应的构造函数来进行实例化得到的,只不过在我们通过字面片量定义的时候JavaScritp引擎自动的调用对应的方法
window 对象
实际上我们直接就能使用的各种方法(全局方法:alert(),confirm()...)或者内置对象(全局对象,Math,JSON,console...)都是 window 对象下的方法也就是说这些全局的方法或者对象实际上是这样被调用和读取的:
window.alert("hello world!")
或者window.Math.max(1,2)
,只不过默认可以省略
函数也是一个特殊的对象
任何函数其实都是一个对象,所以我们也可以给函数添加属性,实际上 call apply bind 这些方法就是函数的属性
function fn(){};
fn.k = 10;
console.log(fn.k); // 10
对象的键也可以是数字,让它变得和数组类似,但是只能通过方括号的方式访问
var likeArray = {
0 : "a",
1 : "b",
2 : "c"
};
console.log( likeArray[0] );// "a"
console.log( likeArray.0 );// Uncaught SyntaxError: missing ) after argument list
引用数据类型
JavaScript 是允许把一个变量赋值给另外一个变量的,不过更据变量初始数据类型的不同,分为两种形式:
非引用数据类型:number,string,boolean,null,undefined
引用数据类型:Object function
非引用数据类型的数据变量相互赋值过后就没有任何的联系
引用数据类型则刚刚相反,变量相互赋值过后,依旧指向初始对象,那也就意味着,对被赋值的之后的变量的改变会影响到初始变量
// 非引用数据类型
var n = 10,z = n;
z++;
console.log( n );// 10
console.log( z );// 11
// 引用数据类型
var obj = {a:10},obj1 = obj;
obj1.a++;
console.log( obj.a );// 11
console.log( obj1.a );// 11
8.05 - 对象的练习
缓存功能
当一个函数的逻辑,运算特别复杂特别多的时候,计算相同的结果会重复的耗费性能,所以我们可以采用缓存的方式来,判断某个值的运算结果是否已经被运算过了,如果是只需要拿到上一次的运算结果从而减少运算次数
// 第一次获取时调用方法
getTagName("div");
// 从第二次开始调用缓存
getTagName("div");
getTagName("div");
function getTagName(name){
if(!getTagName.cache)getTagName.cache = {};
var cache = getTagName.cache[name];
return cache?
cache:
(getTagName.cache[name] = document.getElementsByTagName(name));
};