javascript对象和函数
1.对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
var obj = { a: 1, 5: 10, true: {} };
// 对象就是一个容器
// 容器中存储了若干个元素,这些元素都是通过名称和值这种方式存储
// 名称 -->key 值--->value 键值对
// 任何数据结构都无法超越对象的键值查找速度
// key 的类型必须是字符型或者Symbol
// console.log(obj.a);
// console.log(obj.true);
// console.log(obj["5"]);
// console.log(obj["true"]);
// console.log(obj)
// 如果obj中key是true,这个属性是一个对象,则在这个对象中添加一个a属性
// obj["true"]["a"]=20;
// obj.true.a=20;
// console.log(obj);
// obj.a=10;//key必须是字符,而且必须是确定的字符
// obj["a"]=10;//key可以是任何类型,但是都会被隐式转换为字符串,也可以是变量
obj["5"] = 123;
// var key="names";
// obj[key]="xietian";//如果给入的是变量,就会将变量的值做为对象的key
obj.key = "xietian"; //以点语法使用属性时,默认属性就是字符串,无法使用变量
// obj["key"]="xietian";
var key = "age";
// obj[key]=12;
obj.age = 13;
console.log(obj);
var key = "names";
var o = {
[key]: "xietian",
};
console.log(o);
var obj = { a: 1, b: 2, c: 3 };
// console.log(obj);//对象没有元素个数,也就是说对象是没有长度,无法确定对象中存储了多少个元素
// 在其他语言中对象的存储是无序的,当遍历时对象的属性是随机遍历
// 对于js来说 属性是按照添加的先后顺序遍历
console.log("a" in obj); //true
console.log("e" in obj); //false
// prop 是一个变量
// for(var prop in obj){
// // 遍历对象的属性名 key
// console.log(prop,obj[prop]);
// }
for (var prop in obj) {
console.log(prop, obj[prop]);
}
var o = { d: 10 };
o.a = 5;
o.c = 10;
o.b = 7;
console.log(o);
for (var prop in o) {
console.log(prop);
}
var a = 3;
var b = a;
a = 10;
console.log(b);
var o = { a: 1, b: 2 };
var o1 = o; //o1{a:1,b:2}
o = { a: 10, b: 2 };
console.log(o1);
var o = { a: 1, b: 2 };
var o1 = o;
o.a = 10;
console.log(o1);
// 栈和堆
// 变量名存储在栈中,在栈中变量名通常对应一个值,值的类型有很多种
// 只有字符型\数值型\布尔型\未定义型\Symbol型 之间可以以值的方式存储在这个栈得变量名对应后
// 除上述外其他类型都是引用类型,引用类型都存储在堆中,并且在堆中以一个引用地址来存储值
// 这种引用类型在栈中使用变量名后面存储堆中对应得引用地址
var o = {
a: 1,
b: 2,
c: "asdlkjaslkdjaskdjaslkdjaslkjdlsakjdsalkd",
d: 1213123,
e: 123214124123213,
f: 12312989832382938293,
};
console.log(o);
// var o={a:1,b:2};
// var o1=o;
// console.log(o1);
// o.a=10;
var o = { d: 100 };
o.a = 10;
o.c = 1;
o.b = 2;
o.aa = 10;
console.log(o);
var o = { a: 1, b: { c: 2 } };
var o1 = { c: 2 };
var o = { a: 1, b: o1 };
o.b.c = 10;
console.log(o1);
// var o={value:1,left:{value:2,left:{value:4},right:{value:5}},right:{value:3,left:{value:6},right:{value:7}}}
var o = {
value: 1,
left: { value: 2, left: {}, right: {} },
right: { value: 3, left: {}, right: {} },
};
console.log(o);
// 内存泄漏和垃圾回收
// var o={a:1};
// o=null;
// o={a:2};
// dispose()
// var o={a:1};
// var o1=o;
// o=null;
// o1=null;
// 内存泄漏 指在运行过程中不断的创建对象,并且这些对象不再做垃圾回收,就会造成内存泄漏
// 垃圾回收 当一个对象不再使用时,将这个对象引用地址赋值的所有变量全部设置为null,当内存超出一定值,系统会自动将这些没有引用的对象回收
// 垃圾管理池 flag
// var o={a:1};
// var o1=o;
// var o2=o1;
// var arr=[];
var o = { a: 1, b: 2 };
delete o.a;
delete o.b;
console.log(o);
// var a=10;
// console.log(window.a);
// delete window.a;//无法删除
// console.log(a);
//var o = { a: 1, b: 2, c: { value: 10 } };
// var o1={};
// for(var prop in o){
// o1[prop]=o[prop];
// }
// console.log(o1)
// // 对象浅复制,
// 当把对象的每一层都完成复制,就叫做对象深复制
var o = { a: 1, b: 2, c: { value: 10 } };
var o1 = {};
for (var prop in o) {
o1[prop] = o[prop];
}
o.a = 10;
o.c.value = 100;
console.log(o);
var o = { a: 1, b: 2, c: { value: 10 } };
var o1 = {};
Object.assign(o1, o); //Object.assign(目标,源) 浅复制
o.a = 10;
o.c.value = 100;
console.log(o1);
// var o1=Object.assign({},o);//把o复制到空对象上,并且返回给o1
// JSON
var obj = {
a: 1,
b: 2,
c: 3,
d: { e: 10 },
f: undefined,
};
// ("a=1&b=2&c=3");
// 将对象转换为JSON格式字符串
var str=JSON.stringify(obj);
console.log(str);
// '{"a":1,"b":2,"c":3,"d":{"e":10}}' 这种格式的字符串叫做JSON字符串
var a='{"a":1,"b":2,"c":"aaa","d":{"e":100}}';
// 将JSON格式字符串转换为对象
var o=JSON.parse(a);
console.log(o);
// 对象深复制
var obj = {
a: 1,
b: 2,
c: 3,
d: { e: 10 },
f: undefined,
};
var o = JSON.parse(JSON.stringify(obj));
obj.d.e = 100;
console.log(o);
</script>
</body>
</html>
2.创建函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
table {
border-collapse: collapse;
width: 1000px;
}
td {
border: 1px solid #000000;
line-height: 30px;
height: 30px;
text-align: center;
font-size: 25px;
}
</style>
</head>
<body>
<script>
// fn();
/* var num=2;
function createTable(){
var table="<table>";
for(var i=0;i<num;i++){
table+="<tr>";
for(var j=0;j<num;j++){
table+="<td></td>";
}
table+="</tr>";
}
table+="</table>";
document.body.innerHTML+=table;
}
document.οnclick=function(){
num++;
createTable()
} */
// 函数就是语句块,在适当的时机执行函数,就可以完成对于该语句块的执行
// function 函数名(参数1,参数2...){ 语句块 }
// 命名函数创建
// function fn(){
// console.log("aaa");
// }
// 函数基于对象创建,所以函数也是对象,typeof时函数 function
// 函数存在堆中,当函数所在的script标签被执行时,先将函数放在堆中,然后再栈中创建变量(函数名)引用堆中的函数地址
// 引用完成后,函数名的变量就会自动生成,生成后再执行当前script的后续语句
// 命名函数可以写在当前标签的任意位置,都可以再任意位置调用
// 匿名函数 当代码执行到这里时,创建一个匿名函数赋值给一个变量
// 只有定义以后才可以调用,之前是不可以的
// var fn1=function(){
// console.log("bbb");
// }
// fn1();
// document.οnclick=function(){
// }
// 自执行匿名函数
// (function(){
// console.log("aaa");
// })();
// ~function(){
// console.log("aaa");
// }();
// +function(){
// console.log("aaa");
// }();
// 构造函数创建法 里面的所有内容都是字符串,没有提示,其次函数再创建时会将字符串转换为代码,消耗极大
// var fn=new Function("a","b","console.log(a+b)");
// function fn(a,b){
// console.log(a+b);
// }
// fn(5,8);
var obj = {
a: 1,
b: 2,
c: function () {
console.log("aaa");
},
};
obj.c();
for (var prop in obj) {
if (typeof obj[prop] === "function") {
obj[prop] = obj[prop].toString();
}
}
console.log(obj);
console.log(JSON.stringify(obj));
console.log(JSON.parse(JSON.stringify(obj)));
// for(var prop in obj){
// if(typeof obj[prop]==="function"){
// obj[prop]=obj[prop].toString();
// }
// }
// console.log(JSON.stringify(obj));
</script>
</body>
</html>
3.函数作用域
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// var a = 3; //全局变量
// function fn() {
// a++; //在函数内修改全局变量,调用函数一次,变量被修改一次
// // console.log(a);
// var b = 5; //这个变量定义再函数内部,所以只能再函数内使用,函数外无法调用
// // 局部变量,当函数执行完成后,局部变量会自动销毁
// // 局部变量无法根据函数执行次数保留累计变量值
// b++;
// console.log(b);
// }
// fn();
// fn();
// console.log(a);
// var a=3;
// fn.a=10;
// fn(100);
// function fn(a){
// // c是参数,c也是局部变量
// // var a;
// // 如果函数中定义了与外部的全局变量相同的名称时,当前函数中无法直接使用全局变量
// // 变量提升
// console.log(a);
// var a=5;
// console.log(a+window.a+fn.a);//局部优先
// }
// var a=10;
// function fns(){
// a=null;
// if(a<10){
// var a=20;
// console.log(a,"____");
// }else{
// console.log(a);
// }
// }
// fns();
// console.log(a);
var a = 5;
var a = function (a, a) {
console.log(a);
var a = 7;
console.log(a);
};
a(7, 8);
// /* function fns(o){
// o=100;
// }
// var a=10;
// fns(a);
// console.log(a); */
function fns(o) {
o = 100;
}
var a = 10;
fns(a);
console.log(a);
// function fns(o) {
// o=100;
// }
// var a= 10;
// fns(a);
// console.log(a);
function fns(o) {
o = { a: 2 };
}
var a = { a: 1 };
fns(a);
console.log(a);
// function fns(o){
// o.a=10;
// }
// var a={a:1};
// fns(a);
// console.log(a);
// var a = { n: 1 };
// var b = a;
// a {n:1}
// b {n:1}
// a.x = a = { n: 2 };
// a = { n: 2 }; //返回值 {n:2}
// console.log(a);
// a.x = { n: 2 }; //---> b.x={n:2};--->b={n:1,x:{n:2}}
// console.log(a);
// a = { n: 2 }; //---> a={n:2}
// console.log(a);
// a.n 2 b.n 1
// a.x undefined b.x {n:2}
//console.log(this===window)
var a = 10;
var obj = {
// 写在属性上的this,一边创建该对象,一边设置值,对象还没有创建完成,所以this仍然指向window
a: this.a,
b: function () {
// console.log(a);//全局a
// console.log(obj.a);
// 写在函数中的this,函数调用时,对象本身一定是创建完成的,谁调用当前函数,this就是谁
console.log(this.a); //谁调用当前b函数,this就是谁
},
c: {
a: this.a,
b: function () {
console.log(this.a);
},
},
};
var o = obj;
console.log(o.a);
obj = { c: 11 };
// console.log(obj)
o.b();
// console.log(o.b)
o.c.b();
</script>
</body>
</html>
4.函数的参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
/*
参数函数的局部变量,可以通过执行函数时将值传递进入函数,赋予对应位置的参数
参数分为形参和实参
函数定义中的参数叫做形参,执行函数传入的数据叫做实参
实参赋值给形参时按照实际顺序一一赋值
参数是弱类型,ES5中参数不能设置默认值,参数必须按顺序给入,参数在传递时如果不需要填入则用逗号分隔
参数如果有不定数量,在ES5中无法设置不定数量,但是在ES5中函数中会自动创建一个局部变量 arguments
*/
// function fn(a, b, c) {
// if (c === undefined) c = 5;
// a = Number(a);
// b = Number(b);
// c = Number(c);
// if (Number.isNaN(a)) return;
// if (Number.isNaN(b)) return;
// if (Number.isNaN(c)) return;
// // a和b就是参数
// // console.log(a,b);
// // b=20;
// var sum = a - b - c;
// console.log(sum);
// }
// var a=10;
// fn(3,undefined,10);
// fn(1,6,"5a");
//fn(9, 2);
// console.log(fn.length);//形参的数量
// fn(1, 2, 3);
// fn("zh", 123, undefined);
// console.log(fn.length);
function max() {
if (arguments.length === 0) return undefined;
if (arguments.length === 1) return arguments[0];
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (max < arguments[i]) {
max = arguments[i];
}
// max=max<arguments[i]?arguments[i]:max;
}
console.log(max);
}
max(-99, 0, 123);
// this
function fn1(f) {
f(); //回调 ,不管回调的函数中原this指向什么,现在统一指向window
}
function fn3(f) {
arguments[0](); //当使用arguments完成回调函数的执行时,不管回调函数中this原指向什么,在这里统一指向当前的arguments
}
var obj = {
a: 1,
fn2: function () {
console.log(this); //window
},
};
obj.fn2();
fn1(obj.fn2);
fn3(obj.fn2);
function fn1(f) {
f(3, 5);
}
function fn2(a, b) {
console.log(arguments.callee); //当前执行的函数 fn2
console.log(arguments.callee.caller); //在那个函数中执行了fn2
console.log(fn2.caller);
}
fn1(fn2);
// fn1(function(a,b){
// // console.log(arguments.callee)
// console.log(arguments.callee.caller);//调用当前函数的函数
// })
</script>
</body>
</html>