js高级小结

01基本对象

var stu={
                name:'zsh',
                age:12,
                eat:function(){
                    console.log(this);
                    // 在基本对象内部this指的是当前的对象。
                    console.log('吃了。。。。')
                }
            }
            stu.eat();
            var stu1={
                name:'ls',
                age:20
            }

02工厂方式创建对象

var stu1=Student('zs',20);
var stu2=Student('ls',13);
var tea1=Teacher('aa',34);

03构造函数方式

// 如果是构造函数,函数名一般大写。
            function Student(name,age){
                this.name=name;
                this.age=age;
                this.eat=function(){
                    // 构造函数中的this指的是当前实例化对象
                    console.log(this)
                }
            }
            // 实例化对象
            var stu=new Student('zs',20);
            var stu2=new Student('ls',18)
            stu2.eat();

04构造函数应用

 var flight=new Product('这是无人机',5999,['白色','渐变色','银色']);
            console.log(flight);
            // 直接通过id名可以选择标签
            title.innerHTML=flight.title;
            btn.onclick=function(){
                flight.buy();
                // 页面跳转
                location.href="03构造函数方式.html";
            }
            flight.buy();

05构造函数+原型方式

function Product(title,price){
                this.title=title;
                this.price=price;
                // this.buy=function(){
                //     counsole.log('hello')
                // }
            }
            var flight=new Product('无人机',4999);
            var mz=new Product('口红',399);
            // 存储的地址不一样。执行的功能一样。
            // 每次实例化对象的时候,都会生成一个buy方法。造成资源的浪费
            // console.log(flight.buy==mz.buy);

            // 每一个构造函数,都有一个prototype属性/对象,该属性的所有方法和属性都能被构造函数继承。
            Product.prototype.buy=function(){
                console.log('购买了。。。。')
            }
            // 如果实例对象没有自己对应的方法,会去构造函数的prototype内部寻找。如果能找到,就会执行该方法。
            console.log(flight.buy==mz.buy);
            // 我们一般会把属性放置在构造函数内部,方法类的放在原型里面。这种方法封装的就称为构造函数+原型方式
            

06构造函数相关概念

// this在普通位置一般指向的是window
			console.log(this);
			// 构造函数的首字母一般大写
			function Product(title,price){
                this.title=title;
                this.price=price;
                this.joinCar=function(){
                	console.log(this.title);
                }
            }
            // 两个this指的都是实例化对象
            Product.prototype.buy=function(){
            	console.log(this);
                console.log('购买了。。。。'+this.title);
            }
            var f=new Product('无人机',5999);
            f.buy();
            f.joinCar();

            // 实例对象的__proto__指向构造函数的prototype
            console.log(f.__proto__==Product.prototype);

            f.__proto__.buy=function(){
            	console.log('您确认购买'+this.title);
            }

            var m=new Product('口红',299);
            m.buy();

            var arr=new Array(10,20,30);

            // 可以通过constructor找到实例对象所属的构造函数
            console.log(arr.constructor==Array);
            console.log(m.constructor==Product);

            // constructor在某些情况下没有那么靠谱,不好用
            // 官方推荐 使用 a instanceof b 判断a是否是b的实例对象
            console.log( arr instanceof Array)

07constructor

function Product(title,price){
                this.title=title;
                this.price=price;
                this.joinCar=function(){
                	console.log(this.title);
                }
            }
            // Product.prototype.buy=function(){
            // 	console.log(this);
            //     console.log('购买了。。。。'+this.title);
            // }

            // 相当于重写了Product.prototype 丢失了constructor属性
            Product.prototype={
            	buy:function(){
            		console.log('买');
            	},
            	joinCar:function(){
            		console.log('加购物车');
            	}
            }
            var p=new Product('口红',399);
            console.log(p.constructor);
            console.log(Product.prototype);

08构造函数使用场景

html代码

<h3 id="title">标题</h3><br>
		京东价<p id="price"></p><br>
		选择颜色<p id="color"></p>

		<script src="common.js"></script>

common.js代码

// 创建函数 把对象封装起来
 function Student(name,age){
    return {
        name:name,
        age:age,
        eat:function(){
            console.log(this);
            // 在基本对象内部this指的是当前的对象。
            console.log('吃了。。。。')
        }
    }
}
function Teacher(name,age){
    return {
        name:name,
        age:age
    }
}
function Product(title,price,color){
    this.title=title;
    this.price=price;
    this.color=color;
    
}

Product.prototype.buy=function(){
    console.log('请问您需要购买'+this.title+'?');
}

js代码

var p=new Product('kouhong',2199,['粉色','白色']);
			title.innerHTML=p.title;
			price.innerHTML=p.price;
			for(var i in p.color){
				console.log(i);
				color.innerHTML+=p.color[i];
			}

09constructor

function Product(name){
                this.name=name;
            }
            Product.prototype={
                // 重写以后丢失prototype属性,可以自己增加。
                constructor:Product,
                buy:function(){
                    alert('您确定了')
                }
            }
            var p=new Product('手机')
            console.log(Product.prototype);
            console.log(p.constructor==Product);

10原型链

// 原型链:当从一个对象那里调取属性或方法时,如果该对象自身不存在这样的属性或者方法,
// 就会去关联的prorotype那里寻找,如果prototype没有。就会去prototype关联的prototype那里寻找。如果还没有,会一直向上寻找
// 直到prototype....prototype..为null。从而形成了原型链(根本上来说就是继承)
// a.isPrototypeOf(b) 判断a是否存在b的原型链中
function Product(name){
                this.name=name;
            }
            console.log(Product.prototype.__proto__==Object.prototype);
            console.log(Object.prototype.__proto__);
            var p=new Product('手机');
            console.log(Product.prototype.isPrototypeOf(p));
            console.log(Object.prototype.isPrototypeOf(p));
var person={
				name:'zs'
			}
			// 通过person创建对象student。类似于继承
			var student=Object.create(person);
			student.zid='101';
			var teacher=Object.create(student);
			teacher.zid='001';

			// 自身不能说存在自身原型链中
			console.log(teacher.isPrototypeOf(teacher));
			console.log(student.isPrototypeOf(teacher));
			console.log(Object.prototype.isPrototypeOf(person));
			console.log(person.isPrototypeOf(teacher));

			// 如果一个对象既有自有属性,又可以继承。自有属性为准
			// zid是teacher继承过来的
			console.log(teacher.zid);
			// a.hasOwnProperty(b)判断b属性是a自有的还是继承过来的
			console.log(teacher.hasOwnProperty('zid'));

11get和set

var circle={
				r:20,
				// get获取值 get 变量名  
				// set设置值 set 变量名
				get acr(){
					return Math.PI*this.r*this.r;
				},
				set acr(value){
					this.r=value;
				}
			}
			// 如果是赋值,自动调用set方法
			circle.acr=100;

			// 如果是获取值,自动调用get方法
			console.log(circle.acr);

12属性特征

var stu={
				name:'zs',
				age:12
			}
			// 正常赋值,属性可以直接修改
			stu.name='小明';
			// 属性可以被遍历出来
			// for (var i in stu){
			// 	console.log(i)
			// }

			// 一般特殊情况才这样使用。
			// 设置属性的时候,可以配置属性特征
			Object.defineProperty(stu,'password',{
				value:123,
				// 是否可被修改
				writeable:false,
				// 是否可以被遍历
				enumerable:false,
				//是否可以被重新配置 
				configurable:false
			})
			// 修改不成功,但是不会报错。writeable false
			stu.password=456;
			console.log(stu.password);
			// 不能被遍历 enumerable是false
			for (var i in stu){
				console.log(stu)
			}

			// 不能被重新配置 configurable是false
			// Object.defineProperty(stu,'password',{
			// 	value:123,
			// 	// 是否可被修改
			// 	writeable:true,
			// 	// 是否可以被遍历
			// 	enumrable:true,
			// 	//是否可以被重新配置 
			// 	configurable:true
			// })

13变量提升

/变量声明

			// 如果一个变量声明,会把声明提升到整个作用域的最前面,赋值还是在原来的位置
			// console.log(a);
			// var a=10;
			// 等价于
			// var a;
			// console.log(a);
			// a=10;


			// 如果变量没有声明,作用域是赋值以后的区域
			//报错a  没有声明在赋值之前没有办法直接使用
			// console.log(a)
			// a=10;

			// 通过该方法定义函数,会把整个函数提升到作用域最前面。
			// add()
			// function add(){
			// 	console.log(111)
			// }


			// 如果通过该方法定义函数,只是把变量的定义提升到作用域最前面
			// 报错 add不是一个函数
			// add()
			// var add=function(){
			// 	console.log(111);
			// }


			// var a=10;
			// function add(){
			// 	// 变量提升,会把变量声明提升到整个作用域最前面
			// 	// js中只有函数的作用域,变量的作用域,是向上寻找距离其最近的开始的函数的{ 变量的作用范围就是该{以内。
			// 	// console.log(a);
			// 	// var a=100;
			// 	// 等价于
			// 	var a;
			// 	console.log(a);
			// 	a=100;

			// }
			// add()


			// function add(){
			// 	var a=100;
			// }
			// add();
			// console.log(a);  报错  a的作用域是函数以内


			function add(){
				a=100;
			}
			// add(); 如果执行函数相当于给a赋值。a没有声明,作用域是赋值以后都可以使用  
			// 如果不执行函数,相当于不会执行赋值语句.a会报错
			console.log(a);

14作用域和作用域链

作用域:在js中只有函数的作用域,在函数内部声明的变量,才能称为局部变量
                全局和局部只是相对来说
作用域链:在某个作用域内使用变量的时候,首先会在该作用域内寻找该变量,如果没有
                会一直向上寻找。这样的一种链式关系就是作用域链。其实指的就是变量的就近原则。

15原型链图

16this指向问题

this指向问题:
                    事件函数中:指向事件源
                    普通函数中:指向的是window对象
                    构造函数中:指向的是实例对象
                    普通对象中:指向的是当前对象

btn.onclick=function(){
				console.log(this)
			}
			function Product(){
				this.buy=function(){
					console.log(this)
				}
			}
			var p=new Product();
			p.buy();

			var stu={
				name:'zs',
				eat:function(){
					console.log(this)
				}
			}
			stu.eat();
			function add(){
				console.log(this)
			}
			add()

17call apply和bind

this指向问题:
                    普通函数中:指向的是window对象
                call apply和bind都可以用来修改this指向。只是使用方式不一样

var stu={
				name:'zs',
				age:12,
				weight:200
			}
			function add(a,b){
				console.log(a,b,this.age)
			}
			// add(1,2);

			// fn.call(所要指向的对象,参数1,参数2,...) 调用fn函数。修改this指向
			add.call(stu,1,3);

			// fn.call(所要指向的对象,[参数1,参数2,...]) 调用fn函数。修改this指向
			add.apply(stu,[1,2]);

			// bind不会直接调用函数 返回一个新的函数 修改了this指向
			var fn=add.bind(stu,1,2);
			fn();

18变量在内存中的存储

基本数据类型:在内存中以值的形式存在。 字符串、数值、布尔类型、null undefined

 复合数据类型:在内存中以地址的形式存在。 对象  

var a=10;
			var b=a;
			a=100;
			console.log(b);


			var stu={
				name:'zs'
			}

			// 传递的是地址
			var stu1=stu;
			stu.name='ls';
			console.log(stu1.name);
		</script>

19深拷贝与浅拷贝

浅拷贝:直接把对象的属性一一赋值,不考虑属性值类型,如果属性值为对象的时候,只要修改一个,其余对象对应数据都会改变

var stu1={};
			stu1.name=stu.name;
			stu1.age=stu.age;
			stu1.hobby=stu.hobby;
			stu1.score=stu.score;
			stu.name='张三';
			stu.hobby[0]="弹吉他";
			console.log(stu1);

深拷贝:如果对象的属性值为基本数据类型,直接拷贝。如果对象属性对应的值对象,需要解析对象,再去拷贝

var stu={
				name:'zs',
				age:14,
				hobby:['唱歌','跳舞'],
				score:{
					math:89,
					english:100,
					lizong:[100,100,200]
				}
			}
var stu1={

			}
			stu1.name=stu.name;
			stu1.age=stu.age;
			stu1.hobby=[];
			stu1.hobby[0]=stu.hobby[0];
			stu1.hobby[1]=stu.hobby[1];
			stu1.score={};
			stu1.score.math=stu.score.math;
			stu1.score.english=stu.score.english;
			var stu2={};
			// 快速实现深拷贝(函数递归调用)
			function deepCopy(a,b){
				for(var key in a){
					var i=a[key];
					if(i instanceof Array){
						b[key]={};
						deepCopy(i,b[key]);
					}else if(i instanceof Object){
						b[key]={};
						deepCopy(i,b[key]);
					}else{
						b[key]=i;
					}
				}
			}
			deepCopy(stu,stu2);
			console.log(stu2);
			// 只要调用deepCopy即可实现深拷贝

20高阶函数

// 函数作为函数的实参。高阶函数
			function add(time,color){
				setTimeout(function(){
					color();
				},time)
			}

			add(1000,function(){
				txt.style.color='red';
			})

			add(2000,function(){
				txt.style.background='lime';
			})


			$('button').click(function(){})

21闭包

闭包:扩大了变量作用域

闭包:缩小变量作用域,防止变量污染

html:

<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>

js:

var btns=document.getElementsByTagName('button');
			for(var i=0;i<btns.length;i++){
				// btns[i].onclick=function(){
				// 	// i全局变量,点击的时候i的值已经是btns.length;
				// 	tags[i].style.background='lime';
				// }

				(function(b){
					btns[b].onclick=function(){
						// i全局变量,点击的时候i的值已经是btns.length;
						btns[b].style.background='lime';
					}
				})(i);
			}

			//计数器
			// 1、可以在函数的外部访问到函数内部的局部变量
			// 2、让这些变量始终保存在内存中,不会随着函数的结束而自动销毁
			var add=(function(){
				var count=0;
				return function(){
					return count+=1;
				}
			})()
			console.log(add);
			console.log(add());
			console.log(add());
			console.log(add());
			console.log(add());

 

自调用函数 ;( function(){})(); 前后都需要有结尾;

(function(){
				// 放置的是一段有特殊功能的代码
				var m=10;
			})();
			
			console.log(m)

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值