set方法有且仅有一个参数,参数是赋值时的值
get方法中不允许有任何参数
函数本身是不允许存储任何值的,使用临时属性,在s执行set方法中,将赋予的值存储在临时属性值中,执行get方法时将临时变量返回
如果仅有set没有get,这个属性就是只写属性;如果没有set只有get方法,这个属性是一个只读属性;可以利用set和get完成常量写入
var obj={
a:1,
_c:0,
b:function(){},
// set有且仅有一个参数
set c(value){
document.documentElement.style.backgroundColor="#"+value.toString(16);
this._c=value ;
},
// get不允许有任何参数
get c(){
return this._c;
}
}
setInterval(function(){
obj.c++;
},16);
ES6中的常量设置
class Box{
// static const EVENT_ID="Event_Id";//ES6中不能写常量
constructor(){
}
static get EVENT_ID(){
return "EVENT_ID";
}
}
console.log(Box.EVENT_ID);
对象在初始创建时有set和get方法,对象创建完成后,不能在对象中增加set和get方法,利用Object.defineProperty()给对象追加属性。
var div =document.querySelector("div");
Object.defineProperties(div,{
_width:{
writable:true,
value:0
},
_height:{
writable:true,
value:0,
},
_bgColor:{
writable:true,
value:0
},
width:{
enumerable:true,
set:function(_value){
this.style.width=_value.toString().indexOf("px")>-1?_value:_value+"px";
this._width=_value;
},
get:function(){
return this._width;
},
},
height:{
enumerable:true,
set:function(_value){
this.style.height=_value.toString().indexOf("px")>-1?_value:_value+"px";
this._height=_value;
},
get:function(){
return this._height;
},
},
bgColor:{
enumerable:true,
set:function(_value){
this.style.backgroundColor=(typeof _value==="string")?_value:("#"+_value.toString(16).padStart(6,"0"));
this._bgColor=_value;
},
get:function(){
return this._bgColor;
},
},
});
setInterval(function(){
div.width++;
div.height++;
div.bgColor+=100;
console.log(div.bgColor)
},100);
当属性没有方法,只存储值时,不需要用set/get方法设置获取,直接用属性即可
set/get只能设置字符串/数,对象/数组等引用地址设置后无意义
import Utils from "./js/Utils.js";
var div=document.querySelector("div");
var obj={
_arr:[],
set arr(value){
if(!Array.isArray(value)) return;
if(this._arr.join()===value.join())return;
div.innerHTML="";
for(var i=0;i<value.length;i++){
let ball=Utils.ce("div",{
width:"50px",
height:"50px",
backgroundColor:"red",
color:"#FFFFFF",
textAlign:"center",
lineHeight:"50px",
borderRadius:"50px",
float:"left"
},div);
ball.textContent=value[i];
}
this._arr=value;
},
get arr(){
return this._arr;
}
}
var t=0;
setInterval(animation,2000);
function animation(){
t++;
obj.arr.push(t);
}
obj.arr的引用地址时_arr,如果不重新给obj.arr赋值,重新设置其引用地址,obj.arr的引用地址就不会改变,调用obj.arr后就不会产生效果
引用地址不变都不会触发obj.arr,只有将obj.arr重新赋值,改变引用地址,才可以触发
import Utils from "./js/Utils.js";
var div=document.querySelector("div");
var obj={
_arr:[],
set arr(value){
if(!Array.isArray(value)) return;
if(this._arr.join()===value.join())return;
div.innerHTML="";
for(var i=0;i<value.length;i++){
let ball=Utils.ce("div",{
width:"50px",
height:"50px",
backgroundColor:"red",
color:"#FFFFFF",
textAlign:"center",
lineHeight:"50px",
borderRadius:"50px",
float:"left"
},div);
ball.textContent=value[i];
}
this._arr=value;
},
get arr(){
return this._arr;
}
}
var a=[];
var t=0;
setInterval(animation,2000);
function animation(){
t++;
a.push(t);
obj.arr=a;
}
对象深比较
compareData(target,source){
for(var prop in target){
if(typeof target[prop]==="object" && target[prop] !== null){
return this.compareData(target[prop],source[prop]);
}else{
if(target[prop] !== source[prop]) return false;
}
}
return true;
}
数据结构
数组
有序列表存储若干个无序的元素。
插入和删除会影响数组的元素的位置和结构,速度较慢
查找数组中的某个值时,需要遍历数组的每一个元素,时间复杂度极高,查找速度慢
注意
普通数组类型
二维数组可以通过经纬坐标获取值,效率较高
二维数组类型
var arr1=["数学","语文","英语"];
var arr2=["张三","李四","王五"];
var arr=[
[12,13,14],
[42,43,44],
[62,63,85]
]
var index=arr2.indexOf("张三");
var i=arr1.indexOf("语文");
console.log(arr[index][i]);//张三的语文成绩
index++;
console.log(arr[index][i]);//李四的语文成绩
index++;
console.log(arr[index][i]);//王五的语文成绩
当仅获取结果/值时,对象方法速度更快,但是当获取上下的数据时,数组的效率更高。
var obj={
张三:{数学:12,语文:13,英语:14},
李四:{数学:42,语文:43,英语:44},
王五:{数学:62,语文:63,英语:64},
}
console.log(obj["张三"]["语文"]);
对象
Set
本质是一个对象,但是Set中key与value相同
仅存储数据
是无重复有序列表,属于散列结构,没有下标,不能使用下标循环遍历,无法通过上下关系直接获取上下的数据
插入和删除不需要考虑位置的移动,插入和删除速度很快。
会自动去除重复元素,元素存在唯一性,可以用于大量的不重复数据存储遍历查找速度也很快,略低于键值对类型(例如 对象)。
集合
不重复
插入时考虑插入的位置,属于散列结构
可以设置多重集
let set=new Set([1,2,3,4,5]);//集
let set1=new Set([2,3,4,5,6]);
let set2=new Set([set,set1])//多重集
console.log(set2);
有长度size
weakSet
Map
是一种有长度的键值对数据结构,具备数组的长度紧密性,又具有对象的键值对方法
获取、删除、查询、遍历速度很快
任何类型都可以作为key使用(对象的key只能是String或Symbol)
可以直接枚举遍历键和值
类似于hashMap,hash表
链式存储结构
var o1={value:2};
var o={value:1,next:o1};
优点
尽量使用Map,减少使用对象存储数据
缺陷
weakMap
集
树
特点
每个元素有0个或多个子节点,没有父节点的节点称为跟节点
每一个非根节点有且只有一个父节点,除了跟节点外,每个子节点可以分为多个不相交的子树
类型
链表
是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的。
链表由一系列节点(链表中的每一个元素称为节点)组成,节点可以在运行时动态生成。
每个节点包括两个部分:一个是存储数据元素的数据域,一个是存储下一个节点地址的指针域。
查找速度较慢
插入删除速度快
非连续性非顺序结构
可以存储大量数据,可以快速改变数据结构
单向链表
var o={value:1};
var o1={value:2,next:o};
var o2={value:3,next:o1};
var o3={value:3,next:o2};
双向链表
var o={value:1};
var o1={value:2,next:o};
var o2={value:3,next:o1};
var o3={value:3,next:o2};
o.prev=o1;
o1.prev=o2;
o2.prev=o3;
堆栈结构
参数
参数是局部变量,优先级高于同名的全局变量
作用
为了解决函数的抽象化、多态化,让代码具备 模块化的功能
js是弱引用型语言,参数可以多样化改变,也因此造成函数中需要对参数做大量的判断
function on(type,data,handler){
if(data.constructor===Function){
//当data是函数时,data作为handler使用,销毁data
handler=data;
data=null;
}
}
on("click",function(){
})
on("click",{a:1,b:2},function(){
})
参数可以作为函数中的初始设置变量
function fnc(num){
//即使在调用fnc时不传参,在函数内部也会给参数设置初值
if(num===undefined) num=0;
num++;
if(num<10) return fnc(num);
return num;
}
在多函数中,参数可以被作为中介值被来回传递并且处理,减少全局变量
function fn1(){
var num=1;
num=fn2(num);
console.log(num);
}
function fn2(n){
n++;
return fn3(n);
}
function fn3(n){
n*=n;
return n
}
fn1();
js中参数没有初始值(ES5),参数没有类型区分(大量判断)
参数的先后问题
ES5参数没有若干(…arg),但是有arguments
return
使用return跳出函数,结束当前内容
使用return返回数据
工厂模式
function ce(type,style){
var elem=document.createElement(type);
Object.assign(elem.style,style);
return elem;
}
var div1=ce("div");
var div2=ce("div");
var p=ce("p");
console.log(div1===div2);//false
//返回对象
function createObj(){
return {
a:1,
b:2
}
}
var o=createObj();
单例模式
仅创建一个内容
var elem;
function createElem(){
if(elem) return elem;
elem=document.createElement("div");
return elem;
}
//上述代码可以改写为下面的形式
function createElem(){
if(!elem) elem=document.createElement("div");
return elem;
}
var a=createElem();
var b=createElem();
console.log(a===b);//true
class Box{
static _instance;
constructor(){
}
static getInstance(){
if(!Box._instance) Box._instance=new Box();
return Box._instance;
}
}
var a=Box.getInstance();
var b=Box.getInstance();
console.log(a===b);//true
class Box{
constructor(){
}
static get instance(){
if(!Box._instance){
//给Box创建一个_instance属性,值为new Box(),不可枚举,不可修改,不可删除,第一次创建完成后不会发生变化
Object.defineProperty(Box,"_instance",{
value:new Box(),
});
}
return Box._instance;
}
play(){
console.log("play");
}
run(){
console.log("run");
}
}
var a=Box.instance;
var b=Box.instance;
console.log(a===b);
Box.instance.play();
Box.instance.run();
中介者模式
export default class Model extends EventTarget{
_data=0;
constructor(){
super();
}
static get instance(){
if(!Model._instance){
Object.defineProperty(Model,"_instance",{
value:new Model(),
})
}
return this._instance
}
set data(value){
this._data=value;
Model.instance.b.play(value);
var evt=new Event("data");
this.dispatchEvent(evt);
}
get data(){
return this._data;
}
}
返回源对象
function fn(obj){
obj.a=10;
return obj;
}
var obj=fn({b:1});
obj=fn(obj);
console.log(obj);
//类似于Object.assign()
如果参数是函数,返回回调函数的结果
function fn1(fn){
return fn(5,6);
}
function fn2(a,b){
return a+b;
}
var sum=fn1(fn2);
console.log(sum);
返回数组或对象,用于返回多个元素
function fn(){
var a=1;
var b=2;
var c=3;
return [a,b,c];
}
let [a,b,c]=fn();//解构
console.log(a,b,c);
function fn(){
return{
a:1,
b:2,
c:3
}
}
let {a,b,c}=fn();//解构
console.log(a,b,c);
返回函数体
function fn(){
return function(){
console.log("aa");
}
}
var f=fn();
fn();
函数的length
有权访问另一个函数作用域中的变量的函数,创建的常用方式为在一个函数内创建另一个函数
function fn1(){
var a=1;
// 返回的函数被存储在全局变量中,且这个返回的函数使用局部变量a,所以a被保存在堆中
return function(){
a++;
console.log(a);
}
}
var f=fn1();
f();
缺点
特点
优点
闭包的使用
var Utils=(function(){
var num=0;
return{
a:function(){
num++;
console.log(num);
},
b:function(){
}
}
})();
Utils.a();
Utils.a();
Utils.a();
解决实际的融合问题
传参时收集参数进行存储,没有参数时返回结果
function curry(fn){
var arr=[];
return function(){
//当传入实参时,将传入的参数与arr连接,并将当前函数返回
if(arguments.length>0){
arr=arr.concat(Array.from(arguments));
return arguments.callee;
}else{
//当不传参时,将arr作为参数带入curry(fn)的参数函数中,并执行该参数函数
return fn.apply(null,arr);
}
}
}
function fns(){
// 接收curry传进来的数组,进行相应的处理
return Array.from(arguments).reduce((value,item)=>value+=item);
}
var s=fns(1,2,3,4,5);
console.log(s);
var sum=curry(fns);
var s=sum(1)(1,2)(1,2,3)();
console.log(s);