gzl的博客

  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

JS关于原型

发表于 2018-08-08 更新于 2019-12-13 分类于 JavaScript

一、实例

1. new Person()在前

1
2
3
4
5
6
7
8
9
Person.prototype.name = 'sunny';

function Person() {}

var person = new Person();

Person.prototype.name = 'cherry';

console.log(person.name); //cherry

2. new Person()在后

1
2
3
4
5
6
7
8
9
Person.prototype.name = 'sunny';

function Person() {}

Person.prototype.name = 'cherry';

var person = new Person();

console.log(person.name); //cherry

3. 改变写法

1
2
3
4
5
6
7
8
9
10
11
12
13
Person.prototype.name = 'sunny';

function Person() {
//var this = {__proto__ : Person.prototype}
}

var person = new Person();

Person.prototype = {
name : 'cherry'
}

console.log(person.name); //sunny
1
2
3
4
5
6
7
8
这样理解
var obj = {name : "a"};
var obj1 = obj;
obj = {name : "b"};

Person.prototype = {name : "a"};
__proto__ = Person.prototype;
Person.prototype = {name : "b"};

4. new Person最后执行

1
2
3
4
5
6
7
8
9
10
11
12
13
Person.prototype.name = 'sunny';

function Person() {
// var this = {__proto__ : Person.prototype}
}

Person.prototype = {
name : 'cherry'
}

var person = new Person();

console.log(person.name); //cherry

二、隐式添加

1
2
3
4
5
6
7
8
9
Person.prototype.name = 'abc';
function Person() {
// let this = Object.create(Person.prototype);
// let this = {
// __proto__ : Person.prototype
// }
}

let person = new Person();

三、继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 继承  

//1.圣杯模式
function inherit(Target, Origin) {
function F() {}
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}

// 2.雅虎写法 闭包
var inherit = (function () {
var F = function () {}
return function (Target, Origin) {
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
}());

Father.prototype.lastName = "G";

function Father() {}
function Son() {}

inherit(Son, Father);

var son = new Son();
var father = new Father();

JavaScript作用域、立即执行函数、闭包、this

发表于 2018-08-08 更新于 2020-03-23 分类于 JavaScript

作用域

定义:所有变量(包括基本类型和引用类型)都存在于一个执行环境中(也称为作用域)当中,这个执行环境决定了变量的生命周期,以及哪一部分代码可以访问其中的变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function a() {
function b() {
function c() {
//something
}
c();
}
b();
}
a();

a defined a.[[scope]] -- > 0 : GO

a doing a.[[scope]] -- > 0 : aAO
1 : GO

b defined b.[[scope]] -- > 0 : aAO
1 : GO

b doing b.[[scope]] -- > 0 : bAO
1 : aAO
2 : GO

c defined c.[[scope]] -- > 0 : bAO
1 : aAO
2 : GO

c doing c.[[scope]] -- > 0 : cAO
1 : bAO
2 : aAO
3 : GO

立即执行函数

立即执行函数,执行完后立即销毁(释放)即针对初始化功能的函数。

对于函数,只有表达式才能被执行,外面有一层括号使之成为表达式。

1
2
3
4
let num = (function (a, b, c) {
let d = a + b + c;
return d;
}(1, 2, 3));

考查知识点

1
2
3
4
5
6
7
let x = 1;
if (function f() {}) {
x += typeof f;
}
console.log(x); // 1undefined
// f函数外加括号, 已经变成函数表达式,
// 不再是函数声明, f已经成为undefined;

compare

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 报错语法错误,只有函数表达式才可以被执行
function foo(x) {
console.log(arguments);
}()

// 下面的写法可以理解为分家了,像下面一样 不执行也不报错
function foo(x) {
console.log(arguments);
}(1, 2, 3, 4, 5)

function foo(x) {
console.log(arguments);
}

(1, 2, 3, 4, 5)

注意理解

1
2
3
4
let test = function () {
console.log('a');
}();
// 在控制台访问test 输出 undefined,执行完后立即销毁

闭包

函数累加器(可以不依赖于全局变量)

1
2
3
4
5
6
7
8
9
10
11
12
function add() {
let count = 0;

function demo() {
count++;
console.log(count);
}
return demo;
}
var counter = add();
counter();
counter();

可以做缓存(存储结构)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 1. 用对象返回两个函数
function test1() {
let food = "apple";
let obj = {
eat() {
if (food != "") {
console.log("I am eating " + food);
food = "";
} else {
console.log("There is nothing!");
}
},
pushFood(x) {
food = x;
}
}
return obj;
}
//用对象的形式返回出来,简化返回两个函数
let person = test1();

person.eat();
person.eat();
person.pushFood('banana');
person.eat();


// 2.用数组返回两个函数
function test2() {
let num = 100;

function a() {
num++;
console.log(num);
}

function b() {
num--;
console.log(num);
}
return [a, b];
}
let myArr = test2();
myArr[0]();
myArr[1]();

可以实现封装,属性私有化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Deng(name, wife) {
let prepareWife = 'xiaozhang';
this.name = name;
this.wife = wife;
this.divorce = function () {
this.wife = prepareWife;
}
this.sayPrepareWife = function () {
console.log(prepareWife);
}
}

let deng = new Deng('deng', 'xiaoliu');

console.log(deng.prepareWife); // undefined
console.log(deng.sayPrepareWife()); //xiaozhang

模块化开发,防止污染全局变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let name = "xyz";

let init = (function () {
let name = "abc";

function callName() {
console.log(name);
}
return function () {
callName();
}
}());

let initDeng = (function () {
let name = "def";

function callName() {
console.log(name);
}
return function () {
callName();
}
}());

init();
initDeng();

闭包的问题

实例一

下面这段代码会打印出十个10

1
2
3
4
5
6
7
8
9
10
11
12
13
function test() {
let arr = [];
for (var i = 0; i < 10; i++) {
arr[i] = function () {
console.log(i);
}
}
return arr;
}
let myArr = test();
for (let j = 0; j < 10; j++) {
myArr[j]();
}

解决方法(将 var 改成 let 或者改成下面这段代码),会打印出 0 - 9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function test() {
let arr = [];
for (var i = 0; i < 10; i++) {
(function (x) {
arr[x] = function () {
console.log(x);
}
})(i)
}
return arr;
}
let myArr = test();
for (let j = 0; j < 10; j++) {
myArr[j]();
}

实例二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}

ul {
list-style: none;
}

li:nth-of-type(2n) {
background-color: red;
}

li:nth-of-type(2n + 1) {
background-color: green;
}
</style>
</head>
<body>
<ul>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
</ul>
<script type="text/javascript">
// 1. 闭包产生的索引皆为4

function test1() {
let liCollection = document.getElementsByTagName('li');

for (var i = 0; i < liCollection.length; i++) {
liCollection[i].onclick = function () {
console.log(i);
}
}
}

test1();

// 2. 解决后索引为0 1 2 3
function test2() {
let liCollection = document.getElementsByTagName('li');

for (var i = 0; i < liCollection.length; i++) {
(function (x) {
liCollection[x].onclick = function () {
console.log(x);
}
}(i))
}
}

test2();
</script>
</body>
</html>

this的经典题目

代码第一行 var 改成 let,运行情况不同……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var name = 222;
let a = {
name: 111,
say() {
console.log(this.name);
}
}

let fun = a.say;
fun(); //222
a.say(); //111

let b = {
name: "333",
say(fun) {
fun();
}
}

b.say(a.say); //222
b.say = a.say;
b.say(); //333
1
2
3
4
5
6
7
8
9
10
let foo = 123;

function print() {
// let this = Object.create(print.prototype)
this.foo = 234;
console.log(foo); // 123
console.log(this.foo); // 234
}
new print();
// foo此时指的是全局的foo,函数中的this不是指的全局

预编译

发表于 2018-08-07 更新于 2019-08-08

一、js运行三部曲

1. 语法分析   2. 预编译   3. 解释执行

二、预编译前奏

暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局对象所有。

如 a = 10 , 则 window.a = 10;

如function test() {var a  = b = 123;}

test();

先将123赋给b,然后声明a,然后将b赋给a;

console.log(b)   -->   123;

console.log(a)   -->   undefined

三、预编译

预编译发生在函数执行的前一刻

局部(AO)

1.创建AO对象  (Activation Object)(执行期上下文)

2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

3.将实参值和形参统一

4.在函数体里面找函数声明,值赋予函数体

全局(GO)            window === GO

1.生成了一个GO对象  Global Object

2.找变量声明,将变量作为GO属性名,值为undefined

4.在函数体里面找函数声明,值赋予函数体

例一:(局部)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function fn(a) {
console.log(a); //f a() {}

var a = 123;

console.log(a); //123

function a() {}

console.log(a); //123

var b = function () {}

console.log(b); //f () {}

function d() {}
}
fn(1);
1.创建AO对象
2.  AO{
        a: undefined,
        b: undefined,
    }
3.  AO{
           a: 1,
        b: undefined,
     }
4.  AO{
        a: function a() {},
        b: undefined,
        d: function d() {}
     }
 执行函数对a赋值
   AO{
        a: 123,
        b: undefined,
        d: function d() {}
    }
 执行函数对b赋值
   AO{
        a: 123,
        b: function () {},
        d: function d() {}
    }

例二:(全局)

1
2
3
4
console.log(a);   //f a() {}
var a = 123;
function a() {}
console.log(a); //123
1.创建GO对象      
2. GO{
        a:undefined;
    }
4. GO{
        a:function () {}   
    }
   执行函数对a赋值
   GO{
        a:123
    }

例三(+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function test(c) {
// var this = Object.create(test.prototype);
// var this = {
// __proto__ : test.prototype
// }
var a = 123;
function b() {}
}

AO{
arguments : [1];
this : window,
c : 1,
a : undefined,
b : function () {}
}
1…3132

gzl

96 日志
14 分类
37 标签
© 2020 gzl
由 Hexo 强力驱动 v3.7.1
|
主题 – NexT.Pisces v7.2.0