文章目录
1. 简介
Mosaic公司
浏览器两大部分:shell部分(用户能看到的部分)和内核部分
内核:渲染引擎(语法规则和渲染)、js引擎、其他模块
两种翻译:解释性语言(慢但可跨平台)和编译性语言(快,移植性不好)
java – javac --> 编译 --> .class --> jvm – 解释执行
javaScript引擎是单线程的
主流浏览器:IE、Chrome、firefox、Opera、Safari、trident、webkit/blink、Gecko、presto、webkit
2. 引入,变量,值类型,运算符
引入
外部使用可以,内部失效
<script type="text/javascript" src="../js.js">
document.write('hello world!!!')
</script>
js基本语法
变量(variable)
不可改变的原始值(stack):Number、Boolean、String、undefined、null
引用值(heap):array、Object、function。。。data、RegExp
错误分两种
1. 低级错误(语法解析错误)
2. 逻辑错误(标准错误,情有所原)
运算操作符
+、-、*、/、等
undefined、null、NaN、“”、0、false ==> false;
// 两个表达式就看第二个表达式
var a = 1 && 2;// a = 2;
var b = 0 && document.write('a');
var c = parseInt(window.prompt('input'));
console.log('working')
3. typeof,类型转换
typedef(num)
// number string boolean object undefined function
显式类型转换
- Number(mix)
- parseInt(string, radix) // radix是基底,进制
- parseFloat(string)
- toString(radix)
- String(mix)
- Boolean()
var demo = undefined;
var num = Number(demo); // NaN
var demo = null;
var num = Number(demo); // 0
var demo = "a";
var num = Number(demo); // NaN
var demo = "123abc";
var num = Number(demo); // NaN
var demo = "-123";
var num = Number(demo); // -123
var demo = "-123.9";
var num = parseInt(demo); // -123
var demo = true;
var num = parseInt(demo); // NaN
var demo = 1010101;
var num = parseInt(demo, 2); // NaN
var demo = null;
var num = demo.toString();
console.log(num) // 报错
var demo = 20;
var num = demo.toString(8); // 基底
console.log(num)
隐式类型转换
- isNaN() 相当于 Number(“gsax”) == NaN
- ++ – + -
- -*/% ->number
-
< <= >=
- == !=
- && ||
- === !== 绝对等于/绝对不等于(不发生类型转换)
isNaN(null) // false
isNaN(NaN) // true
isNaN("abc") // true
isNaN(undefined) // true
var demo = "abc"
demo ++ // NaN
var demo = +"abc" // NaNs
var demo = +"123" // 123
1 == "1" // true
1 != true // false
// 隐式转换
2 > 3 < 1 // true
2 > 1 > 3 //false
undefined > 0 // false
undefined < 0 // false
undefined == 0 // false
null > 0 // false
null < 0 // false
null == 0 // false
undefined == null // true
NaN == NaN // false 非数啥也不等于
console.log(typeof(a)) // undefined
console.log(typeof(typeof(a))) // string
![[test.png]]
底部————————————
4. 函数
高内聚,弱耦合
function a(){
var b = 10;
}
console.log(a)
// 匿名函数表达式
var test = function(){}
// 命名函数表达式
var test = function a(){}
// 形式参数 -- 形参
function sum(a, b){}
// 实际参数 -- 实参
sum(1, 2)
function sum(a){
for(var i = 0; i < arguments.length; i++)
console.log(arguments[i]);
}
sum(1, 2, 3, 4, 6) // 可以运行
function sum(a){
// 形参大小与实参长度
if(sum.length > arguments.length)
document.write("sum > arguments")
else
document.write("sum < arguments")
}
sum(1, 2, 3, 4, 6)
function sum(a){
arguments[0] = 2;
document.write(a);
}
sum(1, 2, 3, 4, 6) // a = 2
5. 递归
找规律
找出口
6. 预编译
作用域的定义:变量(变量作用又称上下文)和函数生效(能被访问)的区域。
全局、全局变量
作用域的访问顺序
通篇扫描
解释执行
// 函数声明整体提升
// 变量 声明提升
- 暗示全局变量:即任何变量,如果未经声明就赋值,此变量归全局所有
- 一切声明的全局变量归全局window所有
- window就是全局的域
function test(){
var a = b = 123;
}
test()
console.log(a) // undefined
console.log(b) // 123
预编译四部曲:
- 创建AO对象(执行期上下文)
- 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
- 将实参值和形参统一
- 在函数体里面找函数声明,值赋予函数体
function fn(a){
console.log(a)
var a = 123;
console.log(a)
function a(){}
console.log(a)
var b = function(){}
console.log(b)
function d(){}
}
fn(1);
- 生成一个GO对象(global object === window)
- 同上
if里面不能定义function
var str = false + 1;
document.write(str);
var demo = false == 1;
document.write(demo);
if(typeof(a) && -true + (+undefined) + ""){
document.write("基础扎实");
}
if(11 + "11" * 2 == 33){
document.write("基础扎实");
}
!!" " + !! " " - !!false || document.write("基础扎实");
7. 作用域精解
[[scope]]:每个javascript 函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供javascript引擎存取,[[scope]]就是其中一个。[[scope]]指的是我们所说的作用域,其中存储了运行期上下文的集合。
作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链
运行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁
查找变量:从作用域链的顶端依次向下查找
![[a函数.png]]
![[函数被执行.png]]
![[b函数的作用域链.png]]
function a(){
function b(){
var bb = 0;
aa = 0;
}
var aa = 123;
b();
console.log(aa); // 0
}
a();
8. 闭包
闭包:当内部函数被保存到外部时,将会生成闭包 。闭包会导致原有作用域链不释放,造成内存泄漏。
小例子:
function a(){
function b(){
var bbb = 234;
document.write(aaa);
}
var aaa = 123;
return b;
}
var demo = a();
demo(); // 123
第二个例子:
function a(){
var num = 100;
function b(){
num ++;
document.write(num);
}
return b;
}
var demo = a();
demo(); // 101
demo(); // 102
闭包的作用:
- 实现公有变量(函数累加器)
- 可以做缓存(存储结构)
- 实现封装,属性私有化
- 模块化开发,防止污染 全局bianliang
function test(){
var num = 100;
function a(){
num ++;
console.log(num)
}
function b(){
num --;
console.log(num)
}
return [a,b];
}
var arr = test()
arr[0](); // 101
arr[1](); // 100
function eater(){
var food = "";
var obj = {
eat : function(){
console.log("I am eating" + food);
food = "";
},
push : function(myfood){
food = myfood;
}
}
return obj;
}
var a = eater();
a.eat();
9. 立即执行函数
针对初始化功能的函数
var num = (function(a, b, c){
var a = 123;
console.log(a);
}(参数))
// 两种
(function(){}()) // 建议这种
(function(){})()
只有表达式才能被执行符号执行(忽略表达式名字)
这个不是立即执行函数:
function test(a, b, c, d){
console.log(a + b + c + d);
}(1, 2, 3, 4);
function test(){
var arr = [];
for(var i = 0; i < 10; i++){
// 执行时才会有i
arr[i] = function(){
document.write(i + " ");
}
}
return arr;
}
var myArr = test();
for(var j = 0;j < 10; j++){
myArr[j]();
}
区别:
function test(){
var arr = [];
for(var i = 0; i < 10; i++){
(function(j){
arr[j] = function(){
document.write(j + " ");
}
}(i))
}
return arr;
}
var myArr = test();
for(var j = 0;j < 10; j++){
myArr[j]();
}
10. 对象
- 用所学的知识点,描述一下你心目中的对象
- 属性的增、删、改、查
- 对象的创建方法
- 字面量
- 构造函数
- 系统自带 new Object()
- 自定义
- Object.create(原型)方法
对象的创建方法
var obj = {} 对象字面量/对象直接量
大驼峰式命名规则
function Person(age){
// var this = {}
this.age = age;
this.name = "Yue";
this.sex = "man";
this.run = function(){
console.log("不敢跑!!");
}
return 123; // 仍然可以用
// return this;
}
var person1 = new Person(18);
console.log(person1.name);
console.log(person1.age);
person1.run();
console.log(new Person().name)
构造函数内部原理:
- 在函数体最前面隐式的加上this = {}
- 执行 this.xxx = xxx;
- 隐式的返回this
11. 包装类
var num = 4;
num.len = 3;
// new Number(4).len = 3 delete
console.log(num.len); // undefined
var str = "abcd";
str.length = 2;
console.log(str); // abcd
console.log(str.length); // 4
var str = "abc";
str += 1;
var test = typeof(str);
if(test.length == 6){
test.sign = "结果是String";
}
console.log(test.sign); // undefined
var a = 5;
function test(){
a = 0;
alert(a);
alert(this.a);
var a;
alert(a);
}
test();
new test();
12. 原型
- 定义:原型是function对象的一个属性,它定义了构造函数制造出的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象
- 利用原型特点和概念,可以提取公有属性
- 对象如何查看原型->隐式属性_proto_
- 对象如何查看对象的构造函数 -->constructor
function Person(){
// var this = { __proto__ : Person.prototype, }
this.name = "J"
}
Person.prototype.name = "D";
var person = new Person();
原型链
绝大多数对象的最终都会继承自Object.prototype
Object.create(原型)
undefined.toString()
null.toString()
num.toString(); -->new Number(num).toString();
Number.prototype.proto = object.prototye
var obj = Object.create(null);
document.write(obj.toString()) // 报错
bug:
0.14 * 100 – > ???
Math.ceil(123.234)
Math.floor(123.999)
Math.random().toFixed(2) * 100 // 有时候不准
call/apply
作用,改变this指向
区别:后面传的参数形式不同
function Person(name, age){
this.name = name;
this.age = age;
}
var person = new Person("deng", 100);
var obj = {};
Persn.call(obj, "cheng", 300);
//console.log(obj);
function Person(name, age){
this.name = name;
this.age = age;
}
function Student(name, age, sex){
Person.call(this, name, age);
// 或者 Person.apply(this, [name, age]);
this.sex = sex;
}
var student = new Student("nu", 123, "man");
13. 继承模式
- 传统形式 ->原型链
过多的继承了没有用的属性 - 借用构造函数
不能继承借用构造函数的原型
每次构造函数都要多走一个函数 - 共享原型 (son.prototype = father.prototpe)
不能随便改动自己的原型 - 圣杯模式
function inherit(Target, Origin){
Target.prototype = Origin.prototype;
}
// 圣杯模式
function inherit(Target, Origin){
function F(){}
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Origin.prtotype;
}
var inherit = (function(){
var F = function(){};
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Object.prototype;
}());
14. 命名空间
管理变量,防止污染全局,适合于模块化开发
var deng = {
smoking : function(){
return this;
} ,
prim : function(){
return this;
}
}
15. 对象枚举
属性表示方法:
obj.prop / obj[“prop”]
var deng = {
wife1 : {name : "liu"},
wife2 : {name : "zhang"},
sayWife : function(num){
return this["wife" + num];
}
}
枚举:
- for in循环,用来遍历对象
- obj.hasOwnProperty(prop),不会打印原型上的属性
- ‘height’ in obj --> true 跟hasOwnProperty的区别
- A instanceof B --> A对象是不是B构造出来的,看A对象的原型链上有没有B的原型
var deng = {
name : 'zhang',
age : 123,
sex : "male",
height : 180
}
for(var prop in deng){
obj.hasOwnProperty(prop) -- >返回布尔值
console.log(obj[prop]);
}
判断[]和{}
Object.prototype.toString.call([]);
16. 克隆
遍历对象
- 判断是否是原始值
- 判断是数组还是对象
- 建立相应的数组和对象
function deepClone(origin, target){
var target = target || {},
toStr = Object.prototype.toString,
arrStr = '[object Array]';
for(var prop in origin){
if(origin.hasOwnProperty(prop)){
if(origin[prop] !== null && typeof(origin[prop]) == "object"){
if(toStr.call(origin[prop] == arrStr)){
target[prop] = [];
}else{
target[prop] = {};
}
deepClone(origin[prop], target[prop]);
}else{
target[prop] = origin[prop];
}
}
}
return target;
}
var obj = {
a : {name : "31"},
b : 211,
c : true
};
var obj1 = new Object();
17. 数组
new Array()
读和写:arr[num] // 不可以溢出读,结果为undefined,arr[num] = xxx,// 可以溢出写
改变原数组
- push、pop、shift、unshift、sort、reverse、splice(从第几位开始截取,截取多少的长度,在切口处添加新数据)
不改变原数组 - concat、join->spilt、
var arr = [1,2,3];
Array.prototype.push = function(){
for(var i = 0; i < arguments.length; i++){
this[this.length] = arguments[i];
}
return this.length;
}
arr.splice(3, 0, 4); // 第三位后添加4
// 1. 必须写两个形参
// 2. 看返回值 1)当返回值为负数时,那么前面的数放在前面
// 2)为正数,那么后面的数在前 3)为0,不动
arr.sort(function(a, b){
return a - b;
})
18. 类数组
- 可以利用属性名模拟数组的特性
- 可以动态的增长length属性
- 如果强行让类数组调用push方法,则会根据length属性值的位置进行属性的扩充
19. try.catch
try {
console.log("a");
console.log(b);
} catch (e) {
console.log("出错了")
alert(e.name + " : " + e.message);
}
Error.name的六种值对应的信息:
- EvalError:eval()的使用与定义不一致
- RangeError:数值越界
- ReferenceError:非法或不能识别的所有数值
- SyntaxError:发生语法解析错误
- TypeError:操作数类型错误
- URIError:URI处理函数使用不当
20. es5.0严格模式
“use strict”; // es5.0的严格模式启用,逻辑最顶端(可以局部)
var obj = {
name : "obj"
}
var name = "window"
function test(){
var name = "scope";
with(obj){
console.log(name);
}
}
- 不能兼容es3的一些不规则语法。使用全新的es5规范
- 两种用法:全局严格模式,局部函数严格模式
- 就是一行字符串,不会对兼容严格模式的浏览器产生影响
- 不支持with,argument,callee,func,caller,变量赋值前必须声明,局部变量必须被赋值(Person.call(null/undefined)赋值什么就是什么),拒绝重复使用属性和参数
X. 其他
ctrl+alt+上键 多个光标
复制 alt+shift+上键
ctrl + G 跳行
ctrl + D 选择相同内容
shift + alt + 鼠标 选择区块
自定义快捷键
shift + alt + a 多行注释