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></body>
<script>
/*
函数也是对象
万事万物是对象---猜测函数也是对象
1.函数也可以点出方法
2.函数也可以点出属性
3.函数都是实例对象
*/
console.log(Object.prototype);
console.log(Object.__proto__);
function fn() {}
fn.call()
// 所有的函数都是Function的实例对象
console.log(Object instanceof Function);
console.log(Array instanceof Function);
console.log(Array.prototype.push instanceof Function);
console.log(alert instanceof Function);
// 以上结果都为true
</script>
</html>
2.研究function
<!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></body>
<script>
// Function 也是个函数
// 作用:用来创建函数的
// 用法:var fn=new Function(参数1,参数2,参数3...,函数体)
// 函数其实都是由 Function创造出来的实例对象
// console.log(Function);
// console.dir(Function);
// 正常写函数
// function fn(a,b){
// return a+b;
// }
// console.log(fn(10,20));
var fn=new Function('a','b','return a+b')
console.log(fn(10,20));
console.log(fn);
console.dir(fn)
// 每个函数都有两个原型 并且为同一个
// prototype 如果一个函数作为构造函数使用,相当于他老公
// __proto__ 如果一个函数看做是一个实例对象 相当于是他爹
</script>
</html>
3.研究function家族原型链
<!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></body>
<script>
// Function 原型
// Function.prototype
console.dir(Function)
console.dir(Function.prototype.__proto__)
console.log(Function.prototype.__proto__===Object.prototype)
console.log(Function.prototype instanceof Object);
console.log(Function.prototype.__proto__.constructor===Object);
console.log(Function.prototype.__proto__.__proto__);
consol.dir(Object.prototype)
// 证明任意一个函数都可以调用Object原型上的方法
function fn(){}
console.dir(fn)
console.log(fn.hasOwnProperty('name'));
</script>
</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></body>
<script>
// Function 原型
// Function.prototype
console.dir(Function)
console.dir(Function.prototype.__proto__)
console.log(Function.prototype.__proto__===Object.prototype)
console.log(Function.prototype instanceof Object);
console.log(Function.prototype.__proto__.constructor===Object);
console.log(Function.prototype.__proto__.__proto__);
consol.dir(Object.prototype)
// 证明任意一个函数都可以调用Object原型上的方法
function fn(){}
console.dir(fn)
console.log(fn.hasOwnProperty('name'));
</script>
</html
5.借用
借用:
什么是借用:把人家的方法拿过来用
有什么目的:非继承关系的代码复用
借用通常会有两个效果:
1.修改this
2.调用函数
怎么借用
call
apply
bind
6.this的指向
<!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>
<input type="button" value="按钮" id="btn" />
</body>
<script>
/*
函数里的this指向
函数的使用情况
1.普通函数(全局函数)function this是window
2.构造函数 --this 是实例对象
3.事件 处理程序 除了IE浏览器 指向都是事件源
在IE浏览器中 attacheEvent 指向都是window
4.回调函数 大多情况下都是window
5.对象的方法- 实例对象
谁调用了函数 this就指向谁
*/
// 普通的this
// function fn(){
// console.log(this);
// }
// fn();
// window.fn()
// 构造函数的this
// function Person(name){
// this.name=name;
// console.log(this);
// }
// var p1=new Person('哈哈哈') ;
// 事件处理程序
var btn=document.getElementById('btn')
// btn.onclick=function(){
// console.log(this);
// };
// btn.addEventListener('click',function(){
// console.log(this);
// });
// IE中的单击事件
// btn.attachEvent("onclick", function () {
// console.log(this);
// });
// 回调函数中 this
// setTimeout(function () {
// console.log(this);
// }, 1000);
// 对象里面的方法
function Person(name) {
this.name = name;
}
Person.prototype.say = function () {
console.log(this);
};
var p = new Person("卡布达");
// p.say();
p.eat = function () {
console.log(this);
var fn = () => {
console.log(this);
};
fn();
};
p.eat();
</script>
</html>
7.call
<!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>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</body>
<script>
/*
call的使用
函数名.call(新的this,参数,参数2,参数3...)
作用:function
1.修改this
2.立刻调用函数
*/
function fn() {
console.log(this);
}
fn()
fn.call({
name: '李白'
})//this 为:{name: "李白"}
// window.Person
function Person(name) {
this.name = name;
}
// window.student
function Student(name, age) {
Person.call(this, name);
console.log(this)
this.age = age;
}
var s = new Student('蝎子莱莱', 10)
console.log(s);//this为: {name: "蝎子莱莱"}
//伪数组转成数组
var boxs = document.getElementsByClassName("box"); //伪数组
console.dir(boxs);
// boxs.forEach((element) => {
// console.log(element);
// });
//es5 转换为数组
// console.log(Array.prototype);
// var arr = Array.prototype.slice.call(boxs, 0, boxs.length);
// console.log(arr);
//es6 已经准备好了将伪数组转成数组的方法
var arr = Array.from(boxs);
console.log(arr);
// arr.forEach((e) => {
// console.log(e);
// });
// 原生对象类型的判断
var date = new Date();
var arr = new Array();
// console.log(typeof date);
// console.log(typeof arr);
var type = Object.prototype.toString.call(date);
console.log(type.substring(8).replace("]", ""));
var type = Object.prototype.toString.call(arr);
console.log(type.substring(8).replace("]", ""));
// console.log(type);
// console.log(type1);
</script>
</html>
8.apply
<!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></body>
<script>
/*
apply
函数名.apply(新的this,[参数1,参数,参数3...])
作用:
1.立刻调用函数
2.修改this
*/
function fn(a, b, c) {
console.log(this);
console.log(a + b + c);
}
fn(10, 20, 30); // this为:Window
fn.apply({
name: "蜘蛛侦探"
}, [10, 20, 30]); //this 为:{name: "蜘蛛侦探"}
// 求数组的最大值和最小值
var arr = [10, 80, 520, 962, 456, 782, 1654, 45];
var aa = Math.max.apply(null, arr); //这种直接大写的构造函数点出来的方法,叫静态方法,里面不涉及this
console.log(aa);
//借用构造函数
function Person(name, age) {
this.name = name;
this.age = age;
console.log(this);
}
var s = new Person("子龙", 20);// this为:Person {name: "子龙", age: 20}
function Student(name, age) {
Person.apply(this, [name, age]);
// console.log(this);
}
// var s = new Student("丸子龙", 20);
</script>
</html>
9.bind
<!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></body>
<script>
/*
bind 作用:不会立刻执行函数 而是把函数的this修改了之后 返回一个函数的副本 通常的作用就是修改回调函数里面的this
用法: 函数名.bind(新的this,参数1,参数2,参数3...)
*/
function fn(a, b, c) {
console.log(this);
console.log(a + b + c);
return 1;
}
var f1 = fn.bind({
name: "呱呱蛙"
}, 10, 20, 30);
console.log(f1());
// function fa() {
// return 9;
// }
// var a = fa();
// console.log(a);
setTimeout((function(){
console.log(this);
}).bind({name:'蟑螂恶霸'}),1000)
</script>
</html>
10.作用域
<!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>
.box {
width: 100px;
height: 100px;
background-color: lawngreen;
float: left;
margin-right: 10px;
}
</style>
</head>
<body>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</body>
<script>
/*
作用域:
1.全局作用域
在我们页面的任何位置都可以访问到
2.菊部作用域(局部)
只能被函数内部访问
3.块级作用域
--es6才有的
--let 关键字
*/
// 全局作用域:window对象 所有的全局变量和全局函数都是window的成员 window的成员可以省略window 直接使用
// 隐式 全局变量(不写var的变量) --不会提升的
a = 10;
function fn() {
b = 20;
}
// console.log(a,b);
console.log(a); //10
// console.log(b); //报错b is not defind
//局部作用域
// 1.隔绝外部的影响
function fn() {
var a = 10;
console.log(a);
}
console.log(a);
fn()
// 块级作用域 指的就是在一个大括号{指定的想要的语法块里}
// let 会形成一个块级作用域
/* {
let a = 10;
}
console.log(a); */
// let的作用
// 是es6推荐使用的 声明变量的关键字
// 1.var 会提升 let不会提升 --不允许在赋值之前使用
// 2.var 没有块级作用域 let有块级作用域
/* console.log(a); //undefined 此时69行只执行了定义部分 ,没有执行赋值操作
var a = 10;
console.log(a); */ //10 此时69行完成了赋值的操作
/* console.log(a); //报错
let a = 10; */
var boxs = document.getElementsByClassName("box");
// console.log(boxs);
/* for (var i = 0; i < boxs.length; i++) {
boxs[i].index = i
boxs[i].onclick = function () {
console.log(this.index);
};
} */
for (let i = 0; i < boxs.length; i++) {
boxs[i].onclick = function () {
console.log(i);
};
}
</script>
</html>
11.作用域中访问数据的规则
<!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></body>
<script>
/*
可以更加方便的管理数据
作用域链的数据访问规则
1.如果当前作用域存在这个数据,优先使用这个数据
2.如果当前作用域没有这个数据,会沿着作用域链向外部寻找
3.如果找到了全局都找遍了 都没有找到 会报错
*/
var a = 10;
function t1() {
// var a = 20;
function t2() {
// var a = 30;
console.log(a);
}
t2();
}
t1();
</script>
</html>
12.原型链上成员访问规则
<!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></body>
<script>
/*
如果一个对象访问成员,在对象上没有找到,会沿着原型链查找
就近原则
1.如果当前对象身上有自己该成员,优先使用该成员
2.如果当前对象身上没有该成员,沿着原型链寻找
3.如果直到尽头.还没有找到,返回undefined
*/
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.gender = "男";
Person.prototype.height = 185;
var p = new Person("鲨鱼辣椒", 14);
console.log(p.name);
console.log(p.age);
console.log(p.gender);
console.log(p.height);
console.log(p.weight);
console.log(Array.prototype);
console.log(Object.prototype);
console.log([1, 2, 3].toString());
// console.log(Array.toString());
</script>
</html>