<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> js高级笔记 </title>
<script>
// <<<<<<<<<<<<<<<<<...js高级笔记...>>>>>>>>>>>>>>>>>>>
// 1. 只有函数才能开辟作用域
// 2. 默认就有一个作用域, 叫全局作用域, 也叫0级作用域,
// 然后在0级作用域上声明的变量和函数, 都处于0级上
// 3. 如果是在0级作用域里声明的函数, 那么这个函数开辟的作用域叫1级作用域, 如果我在1级作用域里声明的函数, 函数开辟的空间叫2级作用域, 以此类推
// 4. 变量访问规则: 先在自己作用域链上访问, 如果自己作用域有, 就访问自己的, 如果没有, 就访问上一级的, 如果上一级再访问上一级, 一直到0级, 还没有就报错
// 就近原则
//0级作用域
// var num = 10; //0级
// f1自己它0级,但是它括号里面的作用域叫1级作用域
// function f1() {
// // var num = 1000; //1级
// // 1级作用域
// // f2在1级,只不过f2开辟的作用域叫2级作用域
// function f2() {
// var num = 2222;
// }
// }
// 短路只存在于 && 和 || 中
// && :一假则假; || :一真则真;
// 如果 && 和 || 中通过左边的式子已经能得到结果, 那么右边的式子就不会被执行了, 这就叫短路
// &&:左边式子为假就短路; ||:左边式子为真就短路;
// 逻辑运算符的运算结果一定是true或者false吗?
// 不一定! 跟短路有关
// 如果没有短路, 整个式子结果是右边表达式的结果
// 如果有短路, 整个式子就是左边式子结果
// 变态题
// var n1 = 1,n2 = 2; ||:左边式子为真就短路;整个式子就是左边式子结果
// var res = ++n1 + n2++ - n1-- || n1 + n2; //n1=1,n2=3
// res = 2 + 2 - 2 = 2 条件成立后边不执行 n1(2)-- = 1 + n2(2)++ = 3
// console.log(res, n1, n2); //2,1,3
// in关键字的使用;
// 在forin里遍历对象、 数组;遍历对象时key是属性名;遍历数组时key是下标;
// 判断属性名或者方法名 在不在某个对象里面,
// 判断的是用引号才代表去找这个属性名, 不加引号都代表找变量的值
// var obj = {name: "jack",age: 16};
// for (var key in obj) {
// console.log(key, obj[key]);
// } // name jack
// var arr = [10,20];
// for (var key in arr) {
// console.log(key, arr[key]);
// } // 0 10 , 1 20 ; 打印下标和值
//报错,没有声明age这个变量,而且window里面默认也没有age这个属性
// console.log( age in obj );
// 判断属性名或者方法名 在不在某个对象里面,
// 因为不加引号代表访问变量的值,变量的值取出来是name所以是在问name在不在obj里面
// var str = "name";
// console.log( str in obj );//true
// 因为加了引号代表就是问str在不在obj里面,因为不在得到false
// console.log( 'str' in obj );//false,
// 在数组中是判断下标和方法在不在里面
// console.log(0 in arr); //true
// delete 关键字的使用;
// delete作用一:删除不规则声明的变量 (没有用 var 声明的变量)
// num = 123;
// delete num;
// console.log(num); //报错 num is not defined(num没有定义)
// delete作用二:删除对象的成员:属性和方法
// var obj = {name:"jack", age:16,
// sayHi:function(){
// console.log('hello');
// }}
// delete obj.age;
// delete obj.sayHi;
// console.log(obj.age); //undefined (在对象中找不到该属性,所以返回 undefined)
// console.log(obj.sayHi); //undefined (在对象中找不到该方法,所以返回 undefined)
// obj.sayHi(); //报错 obj.sayHi is not a function (obj.sayHi 不是一个函数,在对象中找不到该方法 )
// 构造函数 首字母大写
//1. 构造函数 - 用来 更加方便的 创建 对象 ---》构造函数 相当于是一个 自定义类
//1.1 创建 构造函数
// a. 变量名 一般用 名词,首字母 大写 --> 方便 一眼认出 这个是 构造函数,最好用 new 关键字来调用
// b. 构造函数中 不需要 我们去手动 创建对象 和 返回 对象
// c. 构造函数 一般 用来 被 new 关键字 调用!!!!
// 1.2 new 关键字 做的4件事情:
// a.创建 空对象
// b.将 空对象 传给 构造函数里 的 this
// c.调用构造函数
// d.返回 对象
// // 构造函数 (首字母大写) (3.调用构造函数;4.将对象 返回 s1)
// function Student(name, age) {this.name = name;this.age = age;}
// // 给原型对象加一个方法叫sayHi;
// 只要给这个构造函数的原型对象加方法,那么这个构造函数实例化出来的对象也有这些方法
// Student.prototype.sayHi = function () {
// console.log('大家好,我叫' + this.name + '今年' + this.age + '岁');
// }
// //实例化对象 (1.创建 空对象,2.将 空对象 传给 构造函数里 的 this);
// var s1 = new Student('渣渣辉',16);
// // 调用方法 (4.返回 对象)
// s1.sayHi();
// 本质上,构造函数也只是普通的函数
// 但是用new调用以后就不普通了
// 因为new做了三件事:
// 1.new在调用时帮我们创建了一个对象
// 2.并且把函数内的this指向了新创建的对象
// 3. 并且会让函数返回值返回这个对象
// var s1 = new Student('zhangsan',16);
// console.log(s1);
// 实例化对象
// 其实就是指:通过函数创建出来的对象,就叫实例化对象
// 如果这个函数本来就是为了让new来调用并生成对象的
// 那么我们就把这种函数叫做构造函数
// 并且会把函数名大写(要起一个名词)
// 原型对象 prototype (指向原型对象)
// 原型对象本质上也是对象, 它是专门配合构造函数的一个对象
// 访问原型对象:构造函数.prototype ;
// 修改原型对象的值: 构造函数.prototype.属性 = 数据;
// Student.prototype.属性 = 数据; 将属性加到原型对象中;
// 实例化对象 (s1) = 数据; 将属性加到(自身)实例化对象(s1);
// 原型对象里只能存公用的方法和属性;
// 只要原型对象里有的属性和方法, 那么实例化出来的对象也有;
// 属性和方法访问规则:如果自己有,访问自己的;如果自己没有,访问原型的;
// 原型对象作用: 保存一些这个构造函数实例化出来的对象和一些相同的方法或属性
// 好处: 不会造成内存空间的浪费和变量名污染
// 只要声明一个构造函数, 浏览器会自动帮它创建一个原型对象
// 实例对象.__proto__( 左右各自两个_)
// __proto__这个属性可以找到实例对象对应的原型对象(已废弃使用)
// 实例对象.__proto__ == 构造函数.prototype
// contructor 属性 (属于原型的,它指向这个原型对应的构造函数)
// 原型对象默认就有个属性叫 contructor, 这个属性可以得到这个原型对应的构造函数
// 实例对象.属性;
// 这个叫访问。 访问规则是自己有访问自己的, 没有访问原型对象的
// 实例对象.属性 = 数据;
// 这个叫修改。 修改永远修改的都是自己的实例对象, 原来有这个属性就修改, 没有就加上
// 原型对象可以被替换
// 如果是替换前创建的对象, 那么指向原来的那个原型对象
// 如果是替换后创建的对象, 那么指向的是新的原型对象
// 原型对象替换后, 不会影响原来创建的实例对象, 但是后面创建的实例对象就被改变了
// Student.prototype.sayHi = function(){console.log('sayHi');}
// var s1 = new Student('jack',16); // 替换前创建的对象
// Student.prototype = {}; // 替换原型
// var s2 = new Student('rose',16); // 替换后创建的对象
// s1.sayHi(); // sayHi
// s2.sayHi(); // 报错(s2.sayHi is not a function) s2.sayHi不是一个函数
// JS其实不叫面向对象, 最多叫基于对象( ES6以前)
// 面向对象三大特征:
// 封装: 把过程代码封装到函数, 函数封装到对象。 别人只要调用对象的方法就行了
// 继承: 指一个类拥有另外一个类的所有成员( 对于ES6而言)
// (对于我们现在而言, 说的是 一个对象拥有另外一个对象的所有成员
// 模拟继承, 只不过我们通过一些技巧能让它可以实现“ 继承” 的效果
// 就像JS没有重载, 但是可以通过arguments模拟重载)
// 多态: 一种行为, 多种实现
// 混合式继承:
// 用forin遍历要被继承的对象, 再把这些成员加到要被继承的构造函数的原型里就行了
// 创建对象
// var xxx = {car: "布加迪威龙",company: '万达'};
// // 构造函数
// function Son(name, age) { this.name = name;this.age = age;}
// // 混合式继承:(遍历要被继承的对象)
// for(var key in xxx){zzz.prototype[key] = xxx[key];}
// // 创建实例化对象
// var s1 = new Son('aaa',30);
// // 打印 实例化对象
// console.log(s1); // 'aaa',30 ,car: "布加迪威龙",company: '万达'
// console.log(s1.constructor); //constructor 指向这个原型对应的构造函数
// //ƒ Son(name, age) {this.name = name; this.age = age;}
// 原型链
// 这些原型对象都像链条一样连接在一起, 所以我们把这种形式叫做原型链
// 原型链最主要的作用是继承。 只要是在原型链上的属性和方法, 这个对象都能用
// 访问规则:先看自己对象里有没有, 有拿来用, 没有找自己的原型, 原型有拿来用, 没有, 再找原型的原型, 有拿来用, 没有继续找;直到找到null, 都还没有, 就返回undefined
// var arr = new Array(10, 20, 30, 40, 50);
// // Array 原型
// console.log(arr.__proto__ === Array.prototype); // true
// // Object原型
// console.log(arr.__proto__.__proto__ === Object.prototype); // true
// // null
// console.log(arr.__proto__.__proto__.__proto__); // null
// function Person() {}
// console.log(Person.prototype.__proto__); // Object 原型
// // Object 原型
// console.log(Person.prototype.__proto__ === Object.prototype); //true
// // null
// console.log(Person.prototype.__proto__.__proto__ ); // null
// 原型: 当创建一个函数的时候, 函数自身会有一些属性的方法, 其中有一个属性叫prototype, 它就是原型。
// 只要是函数都有原型
// 原型是解决性能问题的。
// 构造函数的原型, 只有它的实例化对象可以使用。
// 对象 都有__proto__( 原型链)
// 类 都有prototype( 原型)
// 函数的三个角色: 1. 函数 2. 对象 3. 类
// 换句话: 如果对象上没有; 还会( 通过自身的原型链) 找到构造函数的原型。 如果还没有会( 通过构造函数的原型链) 找到Object的原型 为止。 再没有就变量( undefined) 函数( 报错)。( 注意: 永远三步走,自身 - > 构造函数的原型 - > Object的原型)
// instanceof语法:
// 对象 instanceof 构造函数
// 语义: 判断构造函数的原型对象, 在不在这个对象的原型链上
// 作用: 如果某个构造函数.prototype在这个对象的原型链上, 就意味着, 这个对 象可以调用构造函数.prototype里面的属性和方法
// function f1() {}
// // Function.prototype在不在f1的原型链上
// console.log(f1 instanceof Function); //true
// // Object.prototype在不在f1的原型链上
// console.log(f1 instanceof Object); //true
// 局部变量, 在它所在的作用域的大括号结束后, 就立即销毁
// 局部变量,声明的时候诞生,也就是说在声明的时候会在内存中开辟一个新的空间
// function f1 () {var num = 10;console.log(num);} // num就销毁了
// f1(); // 10; // console.log(num); // 报错;
// 闭包作用: 可以延长局部变量的生命周期
// 什么是闭包?闭包首先是一个函数, 是一种可以访问别的函数内部变量的函数
// 闭包其实是函数内部和外部一个桥梁
// 闭包写法之一:返回函数法
// function 外函数() {
// function 闭包() {//访问外函数内声明的变量}
// return 闭包;}
// 引用函数法
// var res;
// function 外函数() {
// function 闭包() {//访问外函数内声明的变量}
// res = 闭包;}
// window引用法
// function 外函数() {function 闭包() { //访问外函数内声明的变量}
// window.res = 闭包;}
// 全局变量去记录局部变量, 不是延长局部变量生命周期, 而只是相当于把这个局部变量的值给保存一份
// 但是它们是不同的空间, 出了作用域还是会被销毁
// 闭包, 完全相当于是延长了局部变量生命周期, 后面用闭包访问这个变量, 访问的还是原本那个局部变量
// 闭包可以延长局部变量生命周期, 在函数外部我们可以用闭包去访问函数内的局部变量
// 遍历所有的li,给它们加点击事件 --- 闭包的做法
// for (var i = 0; i < liList.length ; i++) {
// function f1() { var sum=i;
// function f2() { alert(sum) };
// returnf2;}liList[i].onclick = f1();};
// 闭包首先是一个函数, 是一种可以访问别的函数内部变量的函数
// 闭包作用: 可以延长局部变量的生命周期,在函数外部我们可以用闭包去访问函数内的局部变量
//闭包其实是函数内部和外部一个桥梁
// 闭包, 完全相当于是延长了局部变量生命周期, 后面用闭包访问这个变量, 访问的还是原本那个局部变量
// 谁调用方法, 方法里的this就是谁 // 1. 如果调用函数时, 前面什么都没加,那么函数里的this就是window
// 2. 谁的前缀调用函数, 函数里的this就是谁
// 3. 计时器调用的函数一定window
// 4. new关键字调用函数, 那么函数里的this是实例出来的对象
//递归指的是一种代码写法:
// 函数自己调用自己, 而且还要有结束的条件能让函数得以结束
// var i=0;
// function f1() {i++;console.log('哈哈' + i);
// if (i < 3) { f1(); }console.log('呵呵' + i);} f1();
// 函数里的 if 判断就是结束条件,当结束判断后再执行后面的代码,if 里的循环调用了几次函数,就执行几次判断后面的代码;
//上下文调用其实本质就是说把函数里的this的指向给改掉
// call用法:函数.call(要修改的this指向的对象, 参数1, 参数2, 参数3, ....参数n)
// 例: getSum.call(obj, 10, 20);(借用) 数组名.push.call(伪数组, 值);
// 直接调用函数前面不加任何前缀, 函数里的this是window
// 如果加了前缀, 前缀是什么对象,里面的this就是谁
// new调用函数, 函数里的this指向新创建的实例化对象
// 计时器里函数的this是window
// 函数可以用这三个方法
// 方法也可以用这三个方法
// 根据原型链,所有函数和方法都相对于是 Function构造函数创建出来的实例对象
// 所以我们可以推理得到: call, // apply, // bind其实都是Function原型对象里的方法
// 所以所有的函数和方法都可以使用call和apply和bind方法
// 正则表达式: 其实就是制定一套规则, 这套规则就叫正则表达式
// 作用: 可以判断某个字符串内容是否匹配这套规则
// 创建一套规则:
// var xx = new RegExp(规则)
// 正则的字面量创建方式 正则 /规则/ //创建了一个正则对象,规则:是要字符串内容包含男
// var re= /男/; // console.log(re.test('申云强有男朋友')); //true
// console.log(re.test('申云强有女朋友')); //false
// 直接写规则再判断是否正确 //console.log(/男/.test( '强人锁男')); //true
// 自定义类:就自己写什么就去匹配什么
// 预定义类:
// . [^\r\n] 除了\r\n以外的字符
// \d [0-9] 数字
// \D[ ^ 0 -9] 非数字
// \s [\t\n\r....空格] 不可见字符
// \S [^\t\n\r....空格] 可见字符
// \w [0-9a-zA-Z_] 数字字母下划线
// \W [^0-9a-zA-Z_]非数字字母下划线
// |: 或 要么左边要么右边
// () 优先级
// [] 里面任意一个
// [^] 取反
// ^ 以什么开头
// $ 以什么结尾
// ^$ 严格匹配,只能匹配你这种规则
// * 0个或多个
// +1 个或多个
// ? 0个或1个
// {n} 指定n个,不能多不能少
// {n,} 至少n个,多了不限
// {n,m} 至少n个,最多m个
// ig 代表既忽略全局大小写
// i 忽略大小写
// g 全局匹配
//调用正则对象 // 正则对象.test(要判断的字符串); // 判断字符串匹不匹配这个规则, 匹配得到true不匹配得到false // replace配合正则 // var str="hello world" ;
// str = str.replace('world','黑马'); // 将 'world' ,替换成'黑马'
// console.log(str); // hello 黑马
// var str="hello world";
// str=str.replace(/o/g, 'z' ); // 将 o 做全局匹配 替换成 z
// console.log(str); // hellz wzrld
// var str ="刘备100关羽200张飞300";
// 把所有数字替换成|
// str=str.replace(/\d+/g, '|' );
// console.log(str); // 刘备|关羽|张飞|
// var str = "oooo哈哈OO呵呵OOO";
// 把所有的大小写o都改成z ; ig代表既忽略大小也全局
// str=str.replace(/o/g, 'z' );
// console.log(str); //zzzz哈哈OO呵呵OOO
// str=str.replace(/o/ig, 'z' );
// console.log(str); // zzzz哈哈zz呵呵zzz
// 清除字符串里所有空
// var str = " 张 三 丰 ";
// console.log(str); // 张 三 丰
// str=str.replace(/\s/g,'');
// console.log(str); //张三丰
// 提取字符串 // var str="hello world" ; // // 提取匹配的字符串,默认只会提取第一个,加一个g代表全部提取 // var res=str.match(/o/g);
// console.log(res); // o o
// 提取邮箱地址
// var str="17672*****@qq.com哈哈"
// var res = str.match( /\w+\S+@[a-zA-Z0-9]+(\.[a-zA-Z]+)+/g);
// console.log(res); // ["17672*****@qq.com"]
// 分组提取
// var str = "zhoulinlin@itcast.cn";
// 从下标0开始截取,截取到@的下标为止(不包括)
// str=str.substr(0, str.indexOf('@'));
//console.log( str); // zhoulinlin
// 给谁打一个小括号,它就会从下标1开始依次出现小括号里的内容
// var res=str.match(/(^\w+)@([a-zA-Z0-9] + )(\.[a - zA - Z] + ) + $ / );
// console.log(res); // zhoulinlin@itcast.cn
// console.log(res[1]); // zhoulinlin
//console.log(RegExp.$1); //对应下标1 //zhoulinlin
// console.log(RegExp.$2); //对应下标2 // itcast
// console.log(RegExp.$3); //对应下标3 // .cn
// BOM: 操作浏览器 alert(); prompt(); window.close(); window.open();
// DOM:操作页面内容
// location对象: 也是BOM一种 操作浏览器地址栏的
// 获得地址栏上的网址
//console.log(location.href);
//获取网址上?和它后面的内容,具体而言代表获取别的网页提交过来的数据
// console.log(location.search);
//获得# 和# 后面的内容 拿到的是锚点
// console.log(location.hash); //
// 获得端口
// console.log(location.port); //
// 获得协议头
// console.log(location.protocol);
// location.reload(刷新网站);
// 相当于是跳转网页
// location.href="http://www.itcast.cn" ;
// 判断账号和密码是否正确, 正确才跳转
// 简写形式:省略href
// location="http://www.itcast.cn" ;
</script>
</head>
<body>
</body>
</html>