lqprototype's Introduction
lqprototype's People
lqprototype's Issues
Javascript继承理解
最近看到一篇文章JavaScript深入之继承的多种方式和优缺点很有感触,在此自己总结一波。
继承
- 原型链继承
- 借用构造函数
- 组合继承
- 寄生组合式继承
原型链继承
function Person() {
this.age = 20;
this.name = 'lq';
this.skill = ["game", "girl", "money"];
}
Person.prototype.residence = ["**", "日本", "美国"];
function YellowPerson() { }
YellowPerson.prototype = new Person();
YellowPerson.prototype.constructor = YellowPerson;
const lq = new YellowPerson();
console.log('lq.constructor:', lq.constructor)
lq.age = 21;
lq.skill.push("music");
lq.residence.push("韩国")
const cx = new YellowPerson();
console.log(cx.age); // 20
console.log(cx.skill); // ["game", "girl", "money", "music"]
console.log(cx.residence); // ['**', '日本', '美国', '韩国']
疑问(主要缺点):
- 原型链继承有哪些缺点?
- 为什么原型链继承不直接YellowPerson.prototype = Person.prototype,有什么缺点?
解答:
- 引用类型的属性(无论是构造函数里面的引用类型和原型链上面的引用类型)被所有实例共享。参考:skill、residence, 当然也有不能向YellowPerson传参的问题。
- 实列不能访问构造函数的属性和方法,YellowPerson可以重写Person原型上面的方法,比如:YellowPerson.prototype.residence = ["北方"],我只是让你继承我的方法和属性,没让你重写我的方法和属性,当然也有第一点的缺点(引用类型共享)
借用构造函数
function Person(name) {
this.age = 20;
this.name = name;
this.skill = ["game", "girl", "money"];
}
Person.prototype.residence = ["**", "日本", "美国"];
Person.prototype.getName = function () {
return this.name
};
function YellowPerson(name) {
Person.call(this, name)
}
const lq = new YellowPerson("KobeBryant");
lq.skill.push("mahjong");
console.log(lq.residence)
console.log(lq.getName()) // Uncaught TypeError: lq.getName is not a function
const cx = new YellowPerson();
console.log(cx.skill) // ['game', 'girl', 'money']
缺点:
- instance不能访问父亲的的原型方法和原型属性(call的原理导致的)
优点:
1.避免了构造函数里面的引用类型的属性被所有实例共享
2.可以在 Child 中向 Parent 传参
组合继承
function Person(name) {
this.age = 20;
this.name = name;
this.skill = ["game", "girl", "money"];
}
Person.prototype.residence = ["**", "日本", "美国"];
Person.prototype.getName = function () {
return this.name
};
function YellowPerson(name) {
Person.call(this, name)
}
YellowPerson.prototype = new Person(name);
YellowPerson.constructor = YellowPerson;
const lq = new YellowPerson("KobeBryant");
lq.skill.push("mahjong");
lq.residence.push("俄罗斯");
console.log('1', lq.residence)
console.log('2', lq.getName())
console.log('3', lq);
const cx = new YellowPerson();
console.log('00', cx.skill);
console.log('11', cx.residence)
console.log('22', cx.getName())
console.log('33', cx);
缺点:
- 每次new YellowPerson("KobeBryant") 都会调用二次构造函数(Person)
- Person原型链上的属性如果是引用类型,会被共享。
- YellowPerson.prototype = new Person(name); 导致YellowPerson.prototype多了很多属性,应该是没有的,应该是继承过来的。
寄生组合式继承
function Person(name) {
this.age = 20;
this.name = name;
this.skill = ["game", "girl", "money"];
}
Person.prototype.residence = ["**", "日本", "美国"];
Person.prototype.getName = function () {
return this.name
};
function YellowPerson(name) {
Person.call(this, name)
}
function F() { }
F.prototype = Person.prototype;
YellowPerson.prototype = new F();
YellowPerson.constructor = YellowPerson;
const lq = new YellowPerson("KobeBryant");
lq.skill.push("mahjong");
lq.residence.push("俄罗斯");
console.log('1', lq.residence)
console.log('2', lq.getName())
console.log('3', lq);
const cx = new YellowPerson();
console.log('00', cx.skill);
console.log('11', cx.residence)
console.log('22', cx.getName())
console.log('33', cx);
缺点:
- 父亲原型链上面的引用类型如何不共享?
hasOwnProperty 思考
正确写法:const hasOwnProperty = (obj, key) => key in obj;
错误写法1
const hasOwnProperty = (obj, key) =>Object.keys(obj).includes(key)
const obj = {a: 1, b: 2, c: 3}
Object.defineProperty(obj, 'abc', {
enumerable: false,
value: 1
})
Object.keys(obj) // ['a', 'b', 'c']
错误写法2
const hasOwnProperty = (obj, key) =>obj.hasOwnProperty('toString')
obj.hasOwnProperty('toString') // false. 不能查找原型链上面的属性和方法
Symbol.iterator 思考
const [a, b] = {a: 1, b: 2}. // 代码成立
考点:
{
[Symbol.iterator]: function(){
return 迭代器
}
}
迭代器:
const arr = [1,2,3]
arr[Symbol.iterator] // ƒ values() { [native code] }
const ite = arr[Symbol.iterator]()
ite.next() // {value: 1, done: false}
应用:
Object.prototype[Symbol.iterator] = function(){
return Object.values(this)[Symbol.iterator]()
}
【数据响应式】理解
数据变化后,会自动重新运行依赖该数据的函数
vue: watch、compoted
react: useEffect、useCallback、useMomeo、memo....
e.stopPropagation() 和 e.stopImmediatePropagation() 区别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// document.addEventListener('click', (e)=>{
// console.log('1');
// });
// document.addEventListener('click', (e)=>{
// console.log('2');
// });
// document.addEventListener('click', (e)=>{
// e.stopPropagation();
// console.log('1');
// });
// document.addEventListener('click', (e)=>{
// console.log('2');
// });
// document.addEventListener('click', (e)=>{
// e.stopImmediatePropagation();
// console.log('1');
// });
// document.addEventListener('click', (e)=>{
// console.log('2');
// });
</script>
</body>
</html>
模块化理解
CommonJS
CommonJS用同步的方式加载模块, 代表:nodejs。在服务端,模块文件都存放在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,更合理的方案是使用异步加载, 所以才有了AMD。
AMD
AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行 , 代表:require.js, AMD推崇依赖前置、提前执行缺点,后面出现了CMD。
CMD
CMD推崇依赖就近、延迟执行。代表: seajs
UMD
CommonJS 和 AMD 结合体。
ES6 Module
浏览器统一化。
彻底搞懂HTTPS的加密机制
Es6 模版字符串思考
const es6 = 'es6'
const tag = ()=> tag
// 备注:styles、setOnclik 未实现,可参考styled-components原理
const str = tag`hello template ${es6}`.styles`color: #d8d8d8`.setOnclik`id:${id}`
应用:这也是[styled-components](https://styled-components.com/) 原理。
const Button = styled.a`
/* This renders the buttons above... Edit me! */
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
margin: 0.5rem 1rem;
width: 11rem;
background: transparent;
color: white;
border: 2px solid white;
/* The GitHub button is a primary button
* edit this to target it specifically! */
${props => props.primary && css`
background: white;
color: black;
`}
`
Es6 class转函数注意点
class Persion {
constructor(name,age){
this.name = name;
this.age = age
}
// 不可被枚举
eat(){
console.log('eat')
}
}
'use strict'
const Persion =(name, age)=>{
if(!this instanceof Persion){
throw new TypeError('')
}
this.name = name;
this.age = age;
}
Object.defineProperty(Persion.prototype, 'eat', {
enumerable: false,
value: function(){
// 不可以被new
if(!this instanceof Persion){
throw new TypeError('')
}
console.log('eat')
}
})
// Persion.prototype.eat = function(){
// console.log('eat')
// }
正则前瞻思考
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.