JavaScript高级(二)

1.1 今日目标

  1. 能够理解js中的内存分配和垃圾回收机制
  2. 能够使用for in循环遍历对象成员
  3. 能够使用delete运算符删除对象成员
  4. 能够理解什么是原型对象
  5. 能够理解原型链的访问规则
  6. 能够实现JS面向对象的继承
  7. 能够灵活使用call或apply
  8. 能够理解this在函数中和页面中的含义

1.2 属性

1.2.1 属性查找原则
<script>
function Student(name){
	this.name=name;
}
Student.prototype.sex='男';
Object.prototype.age=22;
//测试
var stu=new Student('tom');
console.log(stu.name);		//tom
console.log(stu.sex);		//男
console.log(stu.age);		//22
console.log(stu.add);		//undefined
</script>

小结:

1、先在对象自身上查找是否有属性,如果有就返回结果

2、如果没有就顺着原型链往上查找,找到就返回结果

3、如果找不到就返回undefined

总之:沿着原型链向上查找。

1.2.2 属性设置原则
<script>
function Student(name){
	this.name=name;
}
var stu=new Student('tom');
stu.name='berry';	//修改name属性
stu.sex='男'		//添加sex属性
console.log(stu.name);	//berry
</script>

小结:

对象有的属性就修改,没有的属性就添加

1.2.3 属性的特征

特征有:可修改、可枚举、可删除

<script>
var stu={
	name:'tom'
};
//添加name属性
Object.defineProperty(stu,'sex',{
	value:'男',
	writable:false,		//不能修改
	enumerable:false,	//不能枚举
	configurable:false 	//不可以删除
});
//测试:不可修改
stu.sex='女'
console.log(stu);		//{name: "tom", sex: "男"}
//测试:不可删除
delete stu.sex			//删除sex属性
console.log(stu);		//{name: "tom", sex: "男"}
//测试:不可枚举
for(var s in stu){
	console.log(stu[s]);	//tom
}
</script>

注意:删除对象的属性用delete。

1.3 函数高级

1.3.1 创建函数

方法一:直接声明

<script>
function fun(){
}
</script>

方法二:匿名函数

<script>
var fun=function(){
}
</script>

方法三:通过构造器定义

语法:

var 函数名=new Function(形参,形参,...,'函数体')

例题:

<script>
var fun=new Function('num1','num2','alert(num1+num2)');
fun(10,20);
</script>

多学一招:如果参数就一个,这个参数就是函数体

<script>
var fun=new Function('alert("锄禾日当午")');
fun();
</script>

应用例题:执行输入在文本域中的JS脚本

<script>
window.onload=function(){
	document.getElementById('code').onblur=function(){
		var fun=new Function(this.value);   //将文本域的内容作为函数体
		fun();
	}
}
</script>
<textarea id="code" cols="30" rows="10"></textarea>

运行结果

在这里插入图片描述

1.3.2 函数的调用模式与this

1、函数调用模式:函数内的this表示window

<script>
function fun(){
	console.log(this);	//Window
}
fun();	//函数调用模式
//相当于
 window.fun();
</script>

2、方法调用模式:方法内的this表示调用方法的对象

<script>
var obj={
	fun:function(){
		console.log(this);		//obj对象
	}
}
obj.fun();		//方法调用模式	{fun: ƒ}
obj['fun']();	//方法调用模式	{fun: ƒ}
</script>

3、构造函数模式:构造函数内的this表示实例化的对象

<script>
function Student(){
	console.log(this);	//this表示实例化的对象stu  Student {}
}
var stu=new Student();
</script>

4、上下文模式

通过call()、apply()、bind()调用
1:调用函数
2::改变函数内部this的指向

小结:

1、如果this在html中表示当前标签对象

<img src='' onmouseover='this.src=""' />    this表示img标签

2、JS中,this在函数外部,总是表示window对象

<script>
console.log(this);		//Window
</script>

3、函数调用模式,this表示window对象

4、方法调用模式,this表示调用方法的对象

5、构造函数调用模式,this表示实例化的对象

1.3.3 思考题

思考题一:

var age=10;
var obj={
	age:20,
	getAge:function(){
		console.log(this.age);
	}
}
obj.getAge();	//20
var f=obj.getAge;
f();			//10

思考题二:

var age=10;
var obj={
	age:20,
	getAge:function(){
		console.log(this.age);			//20
		function show(){
			console.log(this.age);		//10
		}
		show();
	}
}
obj.getAge();

思考题三:

var length=10;
function fn(){
	console.log(this.length);
}
var arr=[fn,'111'];
fn();			//10	this表示window
arr[0]();		//2		this表示arr

思考题四:

var length=10
function fn(){
	console.log(this.length);
}
var obj={
	length:5,
	method:function(){
		fn()				//window.length	10
		arguments[0]();		//arguments		3
	}
}
obj.method(fn,10,5);

小结:this指向与调用模式有关系,与在什么地调用没有关系。

1.3.4 函数本身也是对象
<script>
function fun(){    //fun本身也是对象
}
console.log(fun.__proto__.constructor);		//Function
console.log(fun.__proto__.__proto__.constructor);	//Object
</script>

原型三角关系
在这里插入图片描述

1.4 call()、apply()、bind()

作用:

1:调用函数
2::改变函数内部this的指向

1.4.1 call()

语法

call(对象,形参,形参,...)

1、通过call调用函数

<script>
function show(){
	console.log(this);		//Window
}
show.call();		调用show()函数
</script>

2、改变函数内部this的指向

<script>
var name='李白';
function show(){
	console.log(this.name);		   //通过call调用的函数中的this表示传递的对象
}
show();			//李白
show.call({name:'tom'});	//	tom		
</script>

好处:方法借用

例题一:

<script>
var stu={
	name:'tom',
	gift:'鲜花',
	express:function(){
		console.log('今天'+this.name+'送你'+this.gift+'作为礼物');
	}
}
stu.express();		//今天tom送你鲜花作为礼物
stu.express.call({'name':'老王','gift':'车'});	//今天老王送你车作为礼物
</script>

例题二:伪数组调动数组的方法

说明:

伪数组:有数字做下标、有length属性,但是不能使用数组的方法

例题

<script>
//伪数组
var stu={
	0:'tom',
	1:'berry',
	2:'ketty',
	length:3
};
[].push.call(stu,'李白','杜甫');
console.log(stu); //{0: "tom", 1: "berry", 2: "ketty", 3: "李白", 4: "杜甫", length: 5}
</script>
1.4.2 apply()

apply的使用和call()是一样的,只是参数有变化

语法

apply(对象,形参数组)

例题:求最大数

<script>
var num=[10,20,35,48,12,17];
var max1=Math.max.call(num,10,20,35,48,12,17);
var max2=Math.max.apply(num,num);
console.log(max1,max2);	//48 48
</script>

面试题:封装打印的方法

<script>
function print(){
	[].unshift.call(arguments,'你好');		//借用unshift方法
	console.log.apply(arguments,arguments);	//借用log方法
}
print('tom','berry')		//你好 tom berry
</script>

call()和apply区别

1、如果参数比较少,使用call()更加方便

2、如果参数已经在数组中,使用apply()方便

1.4.3 bind()

语法

fn.bind(参数) :创建并返回一个和fn一样的函数,函数内的this指向args参数

例题

<script>
var fn1=function(){
	console.log(this);
}
fn1();		//Window 
var fn2=fn1.bind(['tom']);	//创建一个和fn1一样的函数
fn2();	//["tom"]
</script>

例题:

<script>
var name='李白';
var obj={
	name:'tom',
	sayHello:function(){
		setInterval(function(){
			console.log('你好:'+this.name);	//你好:李白
		}, 1000);

		setInterval(function(){
			console.log('你好:'+this.name);	//你好:tom
		}.bind(this), 1000);
	}
}
obj.sayHello();
</script>

1.5 封装

js中封装体现在public、private上,js中不能直接使用这两个关键字。

public:在构造函数里通过this声明的成员都是公开的,在函数内部、外部都可以访问。

private:在构造函数里边声明局部变量,就是私有成员。

<script>
function Student(){
	this.name='李白';		// 公有的
	var phone='13654566'	//	私有的

	var test=function(){
		console.log('这是一个私有的方法');
	}

	this.show=function(){	//公有的方法
		test();	//在公有的方法中调用私有方法
		console.log('这是一个公有的方法');
	}

}
var stu=new Student();
console.log(stu.name);		//李白
console.log(stu.phone);		//undefined
stu.show();
</script>

1.6 继承

1.6.1 原型继承

语法:

构造函数.prototype.成员=成员值		--原型继承

构造函数.prototype=对象			  --原型替换

例题:原型继承

<script>
function Student(){
	this.name='tom';
}
//原型继承
Student.prototype.exam=function(){
	console.log(this.name+'要考试');
}
//测试
var stu=new Student();
stu.exam();		//tom要考试
</script>

例题:原型替换

<script>
function Student(){
	this.name='tom';
}
//原型替换
Student.prototype={age:20,add:'上海'};
var stu=new Student();
console.log(stu.name,stu.age,stu.add);	//tom 20 上海
</script>

注意:原型替换以后,原型就没有constructor属性。

解决方法:手动添加constructor属性

<script>
function Student(){
	this.name='tom';
}
Student.prototype={
	age:20,
	add:'上海',
	constructor:Student		//手动添加constructor属性
};
var stu=new Student();
console.log(stu.__proto__.constructor)   // Student
</script>
1.6.2 混入式继承

特点:只继承自己没有的属性。将属性添加到对象上

<script>
function Student(){
	this.name='学生';
}
//混入式继承
Student.prototype.extend=function(obj){
	for(var k in obj){
		if(this.hasOwnProperty(k))	//如果自己有这个属性就进入下一个循环
			continue;
		this[k]=obj[k];
	}
}
//测试
var stu=new Student();
stu.extend({'name':'tom','age':20,'add':'上海'});
console.log(stu); //Student {name: "学生", age: 20, add: "上海"}
</script>

注意:hasOwnProperty:判断是否是自己的属性

1.6.3 混入+原型继承

特点:只继承自己没有的属性。将属性添加到对象的原型上

<script>
function Student(){
	this.name='学生';
}
//混入式继承
Student.prototype.extend=function(obj){
	for(var k in obj){
		if(this.hasOwnProperty(k))	//如果自己有这个属性就进入下一个循环
			continue;
		this[k]=obj[k];
	}
}
//混入+原型继承
Student.prototype.extend({'name':'tom','age':20,'add':'上海'})
var stu=new Student();
console.log(stu);
</script>

在这里插入图片描述

1.6.4 经典继承

特点:创建一个空对象,这个对象继承指定的对象

<script>
var stu={
	name:'学生',
	age:22
};
var obj=Object.create(stu);	//创建一个空的对象,这个对象的原型是参数stu
console.log(obj);	//{}
console.log(obj.__proto__);	//stu对象
console.log(obj.name,obj.age);	//学生 22
</script>
1.7.5 call和apply实现继承
<script>
function Person(name,sex){
	this.name=name;
	this.sex=sex;
}
function Student(name,sex,score){
	//Person.call(this,name,sex);
	Person.apply(this,arguments);	//效果同上
	this.score=score;
}
var stu=new Student('tom','男',88);
console.log(stu);	//Student {name: "tom", sex: "男", score: 88}
</script>

1.7 多态

在JS中模拟多态

1、在函数内部使用arguments关键字实现多态

2、通过更改this指向可以实现多态(call和apply、bind)

1.8 静态成员

将成员添加到构造器上。

<script>
function Student(){
	this.name='tom';
}
Student.add='中国';		//相当于添加了静态成员(添加在构造器上)
var stu=new Student();
console.log(stu.add);		//undefined
console.log(Student.add);	//中国
</script>

1.9 JSON对象

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON格式和字面量或者数组格式是一样的。

在JS中,中括号表示数组,大括号表示对象

1.9.1 PHP生成JSON数据
<?php
//1、将索引数组转成JSON格式
$stu=array('tom','berry','ketty');
echo json_encode($stu),'<br>';	//转成JSON格式	["tom","berry","ketty"]

//2、将关联数组转成JSON格式
$stu=array('name'=>'tom','sex'=>'男');
echo json_encode($stu),'<br>';	//{"name":"tom","sex":"\u7537"}

//3、将二维数组转成JSON格式
$stu=[
	['name'=>'tom','age'=>20],
	['name'=>'berry','age'=>22]
];
echo json_encode($stu),'<br>';	//[{"name":"tom","age":20},{"name":"berry","age":22}]

//4、将对象转成json格式
class Student{
	public $name='tom';
	private $add='上海';
}
$stu=new Student();
echo json_encode($stu);	//{"name":"tom"}
1.9.2 JSON转成PHP格式
<?php
$str='["tom","berry","ketty"]';
print_r(json_decode($str));	//Array ( [0] => tom [1] => berry [2] => ketty ) 
echo '<br>';
$str='{"name":"tom","sex":"\u7537"}';
print_r(json_decode($str));	//stdClass Object ( [name] => tom [sex] => 男 )
19.3 JavaScript操作JSON数据

和操作字面量对象、数组是一样的。

<script>
var stu={
	'name':'tom',
	'score':{
		'ch':80,
		'math':90
	}
}
console.log(stu.name);				//tom
console.log(stu['score'].ch);		//80
console.log(stu.score.math);		//90
</script>

1.10 垃圾回收机制

机制一:引用计数算法,如果一个内存没有被引用,就被垃圾回收机制视为垃圾。

缺点:不能解决环形引用的问题

在这里插入图片描述

机制二:标记/清除算法:当程序执行完毕后,被变量做标记。

第一步标记变量,不清除的做个标记,清除的不用做标记

第二步遍历所有变量,清除没有标记的变量

1.11 异常Exception

代码一旦出错,后面的代码就终止执行,这样用户体验不好。

一旦有错误就抛出异常,处理完异常以后继续执行。

使用try、catch、finally关键字

<script>
try{
	var obj=new 20();
}catch(ex){
	console.log('错误:'+ex);
}finally{
	console.log('finally块必须要执行')
}
console.log('锄禾日当午');
</script>

运行结果

在这里插入图片描述

1.12 调试技术

方法一:输出消息

document.write()
alert()
console.log()
console.dir()

方法二:异常处理

try-catch语句

方法三:添加断点

  使用debugger关键字添加断点
  使用浏览器调试工具添加断点

使用debugger添加断点

<script>
debugger;		//添加断点
for(var i=1;i<=5;i++){
	console.log(i);
}
</script>

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值