apply和call:改变this指向
//apply和call的使用方法
/*
* apply的使用语法:参数以数组的形式传递
* 函数名或方法名.apply(对象,[参数1,参数2,...]);
* call的使用语法:参数以枚举的形式传递
* 函数名或方法名.call(对象,参数1,参数2,...);
* 想要使用其他对象的某个方法:其他对象.方法名.apply(当前对象,参数,...);
* 这个方法就会被当前的对象所使用,同时这个方法中的this就是当前的对象,在调用方法的时候改变了this的指向
* 作用:改变this的指向
* 不同的地方:参数传递的方式是不一样的
*
* 只要是想使用别的对象的方法,并且希望这个方法是当前对象的,那么就可以使用apply或者是call的方法改变this的指向
*
* 实例对象调用方法,方法要么在实例对象中存在,要么在原型对象中存在
* */
function f1() {
console.log(this);
}
//f1是函数,f1也是对象
f1.apply();
f1.call(); //对象调用方法,说明该对象中有这个方法
console.log(f1.__proto__==Function.prototype);
//所有的函数都是Function的实例对象
console.log(Function.prototype);//ƒ () { [native code] }
//apply和call方法实际上并不在函数这个实例对象中,而是在Function的prototype中
#call() & apply()
<script type="text/javascript">
/*
* call()和apply()方法:
* 这两个方法都是函数对象的方法,需要通过函数调用来实现
* 当对函数调用call()和apply()方法时,都会调用函数执行
* 在调用call()和apply()方法时,可以将一个对象设置为第一个参数
* 此时,这个对象会成为函数调用时的this
* call()方法可以将实参在对象后依次传递
* apply()方法需要将实参封装到一个数组中统一传递
*
* this:
* 1.以函数的形式调用时,this永远都是window
* 2.以方法的形式调用时,this永远是调用方法的对象
* 3.以构造函数的方式调用时,this是新创建的对象
* 4.使用call和apply调用时,this是指定的那个对象
*/
function fun()
{
console.log(this.name);
}
var obj1 = {
name:"obj1的name"
}
var obj2 = {
name:"obj2的name"
}
fun.call(obj1);// obj1的name
fun.apply(obj2);// obj2的name
function fun2(a,b)
{
console.log("a="+a);
console.log("b="+b);
}
fun2.call(obj1,1,2);
fun2.apply(obj2,[1,2]);
//输出 a=1,b=2
</script>
bind:复制并改变this指向
bind方法:复制,参数可以在复制的时候传,也可以在复制之后的调用时传。
语法:函数名或方法名.bind(对象,参数1,参数2,…); //返回值是复制之后的这个方法或函数
//函数使用bind方法,null表示this指向window
function f1(x,y){
console.log(x,y)
}
var ff = f1.bind(null)//将函数f1复制给ff,同时this指向window
ff(1,2)
//方法使用bind,改变this指向
function Person(age){
this.age = age
}
Person.prototype.play = function(){
console.log(this+this.age)
}
function Student(age){
this.age = age
}
var per = new Person(1)
var stu = new Student(2)
var pp = per.play.bind(stu)//把per的play方法复制给pp,同时将this指向stu对象
pp()
函数成员
name属性—>函数名,name属性是只读的,不能修改
arguments属性—>实参的个数
length属性—>函数定义的时候形参的个数
caller属性—>调用者
函数作为参数使用
函数作为参数的时候,如果是命名函数,那么只传入命名函数的名字,没有括号
function f1(fn){
fn();//参数作为函数调用
}
//传入匿名函数
f1(function(){
console.log('我是匿名函数')
});
function f2(){
console.log('我是命名函数')
}
f1(f2)//传入命名函数,只传函数名
获取某个对象的数据类型:
Object.prototype.toString.call(对象);
var arr=[10,20,30];
console.log(Object.prototype.toString.call(arr));//[object Array]
console.log(Object.prototype.toString.call(new Date()));//[object Date]
使用sort方法对数组进行排序
匿名函数作为sort方法的参数使用
var arr = ["acdef","abcd","bcedf","bced"];
arr.sort(function(a,b){
if(a>b){
return -1;
}else if(a==b){
return 0;
}else{
return 1;
}
})
console.log(arr);//["bcedf", "bced", "acdef", "abcd"]
JS中作用域
在一对大括号中定义的变量,是全局变量。
在函数中定义的变量,是局部变量。
只有定义新的函数,才会开启新的作用域。
this:普通函数/方法和es6中箭头函数中this指向的区别
在普通函数/方法中,谁调用this就指向谁
<script type="text/javascript">
/*
* this对象
* 解析器在调用函数时,每次都会向函数内部传递一个隐含的参数this
* 根据函数调用方式的不同,this会指向不同的对象
* 1. 以函数的方式调用时,this永远都是window
* 2. 以方法的形式调用时,this就是调用方法的对象
* 3. 构造函数中的this 和 原型对象中方法的this 都是指向 实例对象
*/
function fun1()
{
console.log(this);
}
fun1(); //输出是 window
var obj = {
name:"孙悟空",
sayHello : fun1
}
obj.sayHello(); //输出是 Object {name: "孙悟空"}
</script>
this.属性名 指向当前对象的属性
<script type="text/javascript">
var name;
function fun1()
{
console.log(this.name);
}
fun1(); //输出是 window
var obj = {
name:"孙悟空",
sayHello : fun1
}
var obj2 = {
name:"猪八戒",
sayHello : fun1
}
obj.sayHello(); //输出是 孙悟空
obj2.sayHello(); //输出是 猪八戒
</script>
在箭头函数中的this,是父作用域中的this,不是调用者
<script>
let p = {
name:'jiaody',
say:function(){
console.log(this)
},
hi:()=>{
console.log(this)
}//此时箭头函数没有定义在其他函数中,所以此时箭头函数属于全局作用域。this指向window
}
p.say();//{name: "jiaody", say: ƒ, hi: ƒ}
p.hi();//Window
</script>
<script>
function Person() {
this.name = 'jiaody';
this.say = function () {
console.log(this)
};
this.hi = () =>{
console.log(this)
}//此时箭头函数定义在构造函数中,所以箭头函数属于构造函数。由于箭头函数的this始终指向其父函数
//所以此时箭头函数中的this就是构造函数中的this
}
var p = new Person();
p.say();//Person {name: "jiaody", say: ƒ, hi: ƒ}
p.hi();//Person {name: "jiaody", say: ƒ, hi: ƒ}
</script>
闭包
//闭包:函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者是数据
//函数形式的闭包:在一个函数中有函数
//如果想要缓存数据,就把这个数据放在外层的函数和里层的函数的中间位置
function f1(){
var num = 10;
return function(){
return num;
}
}
var f2 = f1()
var result = f2()
console.log(result)//10
//对象形式的闭包:在一个函数中有对象
function func(){
var num = 100;
return {
score:num
}
}
var obj = func()
console.log(obj.score)//100
//普通的函数
function f1() {
var num = 10;
num++;
return num;
}
console.log(f1());//11
console.log(f1());//11
console.log(f1());//11
//函数模式的闭包
function f2() {
var num = 10;
return function () {
num++;
return num;
}
}
var ff = f2();
console.log(ff());//11
console.log(ff());//12
console.log(ff());//13
垃圾回收
/*
* 垃圾回收机制GC
* 垃圾:当一个对象没有任何的变量或属性对其进行引用,再也无法对其进行引用,此对象就是垃圾
* 这种对象过多,会占用大量的内存空间,导致程序运行变慢,必须进行垃圾清理
* 垃圾回收机制,会自动将垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收操作。
* 将不再使用的对象设置为null,即可。
*/