前言
秉着学习、交流、思考、总结的态度,和大家分享这段时间通过阅读js高级程序设计,发现的一些小细节,小知识点,一起交流,一起进步!查漏补缺ing...
操作符----instanceof
- 在 JavaScript 中,我们判断一个变量的类型常常会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 "object";
- instanceof 与 typeof 方法不同的是,instanceof 方法帮助开发者明确地确认对象为某特定类型。
var obj = new Object("some texrt");
console.log(obj instanceof Number); //输出 false
console.log(obj instanceof String); //输出 true
原理
:instanceof是根据引用数据类型的prototype来判断真实的数据类型。
变量、作用域和内存问题
-
复制变量值问题
-
var num = 2; var num1 = num; // 此时 num1 = 2 复制了num var num1 = 3; //此时num1 = 3,num依然为2
-
var obj1 = new Object() var obj2 = obj1; obj1.name = "MG"; alert(obj2.name); //此时obj2.name = MG
变量对象的指向: obj1创建了一个对象新实例,然后复制给了obj2。此时他们指向的都是堆内存中的同一个对象;当obj1添加name属性之后,obj2来访问这个属性,此时他们访问的都是存储在这个堆内存中的一个对象。
-
-
声明变量
function add(num1,num2){ var sum = num1+num2; return sum; } var result = add(10,20); alert(sum); // sum is not defined---(var声明在了局部环境,全局无法访问到)
function add(num1,num2){ sum = num1 + num2; return sum } var result = add(10,20) alert(sum); // 30
var: var声明变量会自动被添加到最接近的环境中;在函数内部最接近的环境就是函数的局部环境;如果初始化变量时(代码块2所示),没有使用var关键字,所以sum属于全局环境,那么当add()执行完毕之后,sum也可以被访问到。
-
垃圾收集机制
- javascript内部机制具有自动垃圾收集机制。不必关心内存分配和回收问题。
标记清除
是主流的垃圾收集算法。另外一种是引用计数
算法。
创建对象
-
工厂模式
- 这是一种广为人知的设计模式,说白了就是实现同一事情的相同代码,放到一个函数中,以后如果再想实现这个功能,就不需要重新编写这些代码了,只要执行当前的函数即可;
- 弊端:这种模式没有解决对象识别的问题(即怎样知道一个对象的类型)用起来还是不够灵活;
function creatPerson(name,age,job){ var o = new Object(); // 新建一个函数 o.name = name; o.age = age; o.job = job; o.sayName = function (){ alert (this.name); }; return o; } var person1 = creatPerson("mangguo",21,"fe"); var person2 = creatPerson("MG",21,"前端");
-
构造函数模式
- 典型用法是:new操作符来创建一个新的对象;注意哦,构造函数模式函数名
首字母
要使用大写
; - 弊端:这种构造函数的方式会导致不同的作用域链和标识符被解析,但是创建新实例的机制仍然是相同的;
function Person(name,age,job){ var o = new Object(); // 新建一个函数 o.name = name; o.age = age; o.job = job; o.sayName = function (){ alert (this.name); }; } var person1 = new creatPerson("mangguo",21,"fe"); var person2 = new creatPerson("MG",21,"前端");
- 典型用法是:new操作符来创建一个新的对象;注意哦,构造函数模式函数名
小伙伴们可以根据这些实例,自己总结一下上边的这两种模式还有什么不一样的地方,进一步巩固哦!
-
原型模式
- hasOwnProperty()方法,可以用来检测一个属性是存在于实例中,还是存在于原型中;
- 只有当实例真正重写原型里边的属性时, hasOwnProperty()才会返回true;
- 使用in操作符时,只要通过对象能够访问到属性就会返回true;
- 要注意区别 hasOwnProperty()和 hasPrototyeProperty();当对象属性重写之后,hasPrototyeProperty()会返回false;
- 实例和原型之间的连接是一个指针
prototype
;
function Person(){} Person.prototype = { name :"MG", adress :"beijing", sayName :(()=>{ console.log(this.name); }) } var person1 = new Person(); var person2 = new Person(); console.log(person1.hasOwnProperty("name")); // 输出 false console.log("name" in person1); // 输出 true person1.name = "mangguo" console.log(person1.hasOwnProperty("name")); // 输出 true console.log("name" in person1); // 输出 true
-
构造函数和原型混成的模式
- 混成模式集两种模式之长,是目前使用最广泛,认同度最高的一种创建自定义类型的方法;
- 这样会最大程度的节省内存,这样的实例就会不仅有自己的实例属性,还会共享着原型上的属性和方法,真正的实现1+1>2;
function Person(name,age,job){ var o = new Object(); // 新建一个函数 o.name = name; o.age = age; o.job = job; this.friends = ["Mar","Court"]; } Person.prototype = { constructor:Person, // 这里是声明所有实例的共享属性,constructor' sayName:function(){ alert(this.name); } } var person1 = new creatPerson("mangguo",21,"fe"); var person2 = new creatPerson("MG",21,"前端"); person1.friends.push("Van"); console.log(person1.friends); // 输出 "Mar, Court, Van" console.log(person2.friends); // 输出 "Mar, Court" ,可以看出修改person1的修改并不会影响到person2 console.log(person1.friends === person2.friends); // 输出 false console.log(person1.sayName === person2.sayName); // 输出 true
除了以上几种模式还有
动态原型模式
、寄生构造函数模式
和稳妥构造函数模式
,但由于这些都不太常用,所以就不介绍了,有兴趣的小伙伴可以参考js红宝书第六章,里边介绍的很详细哦!
小结
这些是在阅读红宝书的过程中,发现的一些小细节,或许还不够深入,需要小伙伴们一起多积累多练习,大家一起学,一起交流进步才会更快哦,一起加油!持续更新中~