前端学习笔记(二)

663 阅读3分钟

今天《JS高级程序设计》和《DOM编程艺术》两本书到了,开始看书。

1.对“在构造函数中定义属性,在原型中定义方法“的理解

1.在原型中定义方法很容易理解,只要理解原型链就能理解。

2.但是属性要在构造函数中定义有什么好处呢?MDN没解释。

查了网上很多资料,都在胡说八道。

于是查了查js高级程序设计,找到了原因。

不是因为属性在构造函数中定义有好处,而是因为部分属性在原型上定义会有坏处。而这指的就是引用值属性,比如说数组。

假设我们有一个构造函数Person,是这样的↓

let Person = function() {};
Person.prototype.name = '魔礼青';
Person.prototype.friends = ['魔礼寿', '魔力红', '魔礼海'];

然后我们实例化两个魔礼青

let Person1 = new Person();
let Person2 = new Person();

现在自然没有什么问题,你可以通过给name属性赋值更改默认的魔礼青这个名字,以下代码↓

Person2.name = '莫里森';

以上代码后,Person2变成了莫里森,Person1不受影响还是魔礼青,这没问题。

但是friends属性的更改就会有问题。比如以下代码↓

Person1.friends.push('魔理沙');

现在问题出现了,由于friends是在prototype里定义的,所以这个push会同时影响到两个人。这样子莫里森和魔礼青都有个friend叫魔理沙了。

因此我们要在构造函数里定义属性,或者说不要在原型里定义引用属性。

2.寄生式组合继承,是继承的最佳方式

MDN和JS书上有一行有区别:

MDN上使用的是Teacher.prototype = Object.create(Person.prototype); // 这是寄生式组合继承

红宝书上还有种组合继承是这样的Teacher.prototype = new Person(); // 这是组合继承

都可以,只是如果按照书上,Person 会被调用两次,一次在盗用构造函数的时候使用 call,一次是在继承的时候实例化,属性会被创建两次,只不过实例的属性遮蔽了原型的属性,这样比较冗余浪费。所以还是按照MDN的寄生式组合继承来最好,避免了多余的属性。如果浏览器不支持create(),倒是可以用书上的来。

(注意不要忘了 Object.create 接受的参数是原型)


↑不会有问题,只要你不主动给Person.prototype和Teacher.prototype加上引用属性。

(顺便此时有Student.prototype.__proto__ === Person.prototype

下面一张图表示我对继承关系原型链的理解

3.提升

突然提到提升,去学习了一下。大概是这样:

先提升变量的声明(var定义的),赋值不提升还在原处。原来的Var a = 1;会变成a = 1;, 然后作用域最顶端处声明这个变量。

函数也会提升,也是最顶端,但是在提升后的变量的下面。

4.JSON

4.1 用XHR读取JSON:

①new一个XHR对象

②初始化,request.open();

③声明返回类型,request.responseType = "json";

④发送请求,request.send();

⑤通过requese.onload = function() {/*数据处理语句*/},当请求返回成功时,运行函数里的语句。

4.2 JSON类型和字符串互换

由于JSON太普及了,浏览器内建了一个JSON对象,可以调用两个方法

JSON.parse(/*JSON格式的字符串文本*/) 把字符串转换成json对象,当然格式要对。

JSON.stringify(/*JSON对象*/) 把对象转换成字符串。